9 MySQL 実行計画の具体的な内容は何ですか? mysqlの説明とは何ですか?
10 SQL の遅いクエリ ステートメントを見つける方法
10.1 位置決め
ほとんどのリレーショナル データベース管理システム (RDBMS) には、遅いクエリを特定するための対応するツールと手法があります。
-
ログ:
- MySQL :スロー クエリ ログ( ) を有効にすると、実行時間が特定のしきい値を超えたクエリをログに記録できます
slow_query_log
。 - PostgreSQL :
log_min_duration_statement
パラメータを設定することで、実行時間が一定の閾値を超えたクエリをログに記録させることができます。 - SQL Server : SQL Server Profiler を使用して、遅いクエリをキャッチします。
- Oracle : AWR (自動ワークロード リポジトリ) レポートと ADDM (自動データベース診断モニタリング) レポートを使用して、遅いクエリを特定します。
- MySQL :スロー クエリ ログ( ) を有効にすると、実行時間が特定のしきい値を超えたクエリをログに記録できます
-
パフォーマンスおよび監視ツール: ほとんどの RDBMS は、実行中のクエリまたは最近実行したクエリのパフォーマンス統計を表示するツールを提供します。たとえば、MySQL にはモジュールがあり
SHOW PROCESSLIST
、PostgreSQL にはpg_stat_statements
モジュールがあります。
結論として、データベースのパフォーマンスを定期的に検査して分析することが、データベースの健全な動作を保証する鍵となります。上記の方法とツールを通じて、遅いクエリを効果的に特定し、最適化できます。
10.2 特定されたスロークエリステートメントを分析し、分析計画を表示する方法
- EXPLAIN コマンド: 遅いクエリであると思われる SQL ステートメントがある場合は、 EXPLAIN コマンド (または SQL Server などの一部のデータベースでは を使用) を使用して、
EXPLAIN PLAN
クエリの実行プランを表示します。これは、クエリが遅い理由を理解し、クエリを最適化するためのヒントを得るのに役立ちます。
10.3 SQL ステートメントを最適化する方法
SQL の最適化は非常に奥深いトピックであり、さまざまな技術や戦略が関係します。一般的な SQL 最適化戦略をいくつか示します。
-
インデックスの適切な使用:
- 頻繁にクエリされる列と WHERE 句内の列のインデックスを作成します。
- インデックスが使用できなくなる可能性があるため、列に対して関数や計算を使用しないでください。
- 複合インデックスを使用してクエリをカバーします。
-
フルテーブルスキャンを回避します。
- これは、WHERE 句でインデックスを使用することで実現されます。
- テーブル全体ではなく、データの一部のみをスキャンする必要があるクエリを検討してください。
-
クエリ構造を最適化します。
- 本当に必要な列のみを選択するには、SELECT 句で要求される列の数を減らします。
SELECT *
テーブル内のすべての列が本当に必要な場合を除き、使用を避けてください。- 必要に応じて、サブクエリの代わりに JOIN を使用します。
-
JOIN を最適化する:
- JOIN 条件でインデックスを使用します。
- JOIN の数を減らし、必要な場合にのみ使用します。
- EXPLAIN を使用して JOIN 操作を分析します。
-
適切なデータ型を使用します。
- 最も適切なデータ型を使用すると、ストレージを削減し、クエリ速度を向上させることができます。
- たとえば、整数を格納するには、VARCHAR ではなく INT を使用します。
-
データベース構造を最適化します。
- データベースを正規化してデータの冗長性を減らします。
- クエリのパフォーマンスを向上させるために、必要に応じて非正規化を使用します。
-
最適化されたサブクエリ:
- 可能な限りサブクエリを JOIN に置き換えてください。
- 場合によってはサブクエリの方が効率的ですが、一般的には JOIN の方が高速です。
-
パーティションを使用します。
- 特定の列の値に基づいて、大きなテーブルをより小さく管理しやすい部分に分割します。
-
結果セットを制限します。
- 特に一部の結果のみが対象となる場合は、LIMIT を使用して結果セットのサイズを削減します。
-
ストレージエンジンの最適化:
- アプリケーションのニーズ (読み取りまたは書き込み集中型など) に基づいて、適切なストレージ エンジンを選択します。
- 定期メンテナンス:
- データを整理し、未使用のスペースを再利用するために定期的に実行されます
OPTIMIZE TABLE
。 - 統計を更新して、クエリ オプティマイザーがより適切な決定を下せるようにします。
- キャッシュを使用する:
- MySQL のクエリ キャッシュを活用します。
- Redis や Memcached などの外部キャッシュ ソリューションを使用します。
-
LIKE 検索など、オーバーヘッドの高い特定の SQL 関数および操作を、特に先頭にワイルドカードを使用して使用することは避けてください。
-
遅いクエリを評価し、場合によっては書き換えます。
- スロー クエリ ログを使用して、最適化が必要なクエリを見つけます。
EXPLAIN
クエリの実行計画を表示し、ボトルネックを特定するために使用します。
これらは、SQL を最適化する一般的な方法のほんの一部です。実際には、データベースとアプリケーションのシナリオごとに、特定の最適化戦略が必要になる場合があります。
11 テーブル内に大量のデータがあり、データベースにないレコードをクエリして、どのレコードも一致しないことが判明した場合、この時点でどのように最適化しますか? もちろん、必ずしも mysql を使用して最適化することを意味するわけではありませんが、他のツールを使用して最適化することを意味する場合もあります。
大きなテーブルに存在しないレコードをクエリする場合、最適化の鍵は、スキャンする必要があるデータの量を減らすことです。この種のクエリを最適化する方法は次のとおりです。
-
適切なインデックスを構築します。
- データベースがテーブル全体のスキャンを実行する代わりにデータを迅速に検索できるように、クエリ対象のフィールドにインデックスが付けられていることを確認してください。
- コマンドを使用して
EXPLAIN
クエリの実行計画を表示し、インデックスが使用されているかどうかを確認します。
-
データベースパーティション:
- 非常に大きなテーブルの場合は、データベース パーティションの使用を検討してください。この方法では、クエリはテーブル全体ではなく、1 つまたはいくつかの関連するパーティションのみを検索する必要があります。
-
データの概要:
- 頻繁にクエリされるフィールドについては、ダイジェスト (ハッシュなど) を計算し、別の列またはテーブルに保存できます。
- データベースにない値をクエリする場合、チェックする必要があるのはダイジェストのみであり、実際のデータはチェックする必要はありません。
-
外部検索エンジンを使用します。
- 複雑な検索ニーズには、Elasticsearch や Solr などの全文検索ツールを使用できます。これらのツールは、データを迅速に検索するのに非常に効果的です。
-
ブルームフィルターを使用します。
- ブルーム フィルターは、要素がコレクション内にあるかどうかを迅速かつ効率的にチェックできるデータ構造です。
- ブルーム フィルターを使用して、データベースにクエリを実行する前に、レコードが存在する可能性があることをフィルターが示しているかどうかを簡単にチェックします。
-
データを削減します:
- テーブル サイズを管理可能な範囲内に保つために、不要になったデータを定期的にアーカイブまたは削除します。
-
キャッシュを使用する:
- 特定のデータセットを頻繁にクエリする場合は、Redis や Memcached などのキャッシュ ソリューションを使用して結果をキャッシュすることを検討してください。こうすることで、一般的なクエリについて、最初にキャッシュを確認できます。
-
ハードウェアと構成の最適化:
- ハードウェア構成が SSD の使用、RAM の増加、ネットワークの最適化などの要件を満たしていることを確認してください。
- データベースの場合、パフォーマンスを向上させるために、バッファ サイズの増加、クエリ キャッシュの調整などを検討してください。
-
アプリケーション層戦略:
- 可能であれば、アプリケーション層で前処理またはチェックを実行して、不必要なクエリを減らすようにしてください。
- たとえば、アプリケーション キャッシュを使用したり、高速検索のためにいくつかのデータ構造を維持したりするなどです。
-
データ ストレージの戦略を検討してください。
- たとえば、クエリの頻度は低いものの、大量のデータが含まれるテーブルの場合は、従来の行ストレージの代わりに列指向ストレージ (Apache Parquet など) を使用することを検討してください。
一般に、大きなテーブルに存在しないレコードのクエリを最適化するには、特定のニーズとデータを深く理解する必要があります。さまざまな戦略やテクノロジーには適用可能なシナリオがあるため、最高のパフォーマンスを達成するには、通常、複数の方法を組み合わせる必要があります。
11.1 適切なインデックスを確立する. 大規模なテーブルの場合でも適切なインデックスを確立することが推奨されるのはなぜですか? 存在しない主キーを使用してクエリを実行する場合、インデックスを使用することになるからです。またはフルテーブルスキャン
存在しない主キーを使用してクエリを実行すると、データベースはテーブル全体のスキャンを実行する代わりに主キー インデックスを使用します。
主キー インデックス (多くのデータベースでは、主キーはデフォルトで一意であり、インデックスが付けられています) は、レコードを高速に検索できるように設計されています。主キー値を使用してクエリを作成すると、レコードが存在しない場合でも、データベースはそのインデックスを検索します。インデックス構造 (B ツリーやハッシュ インデックスなど) の設計により、データベースはテーブル全体をチェックすることなく、レコードが存在するかどうかを迅速に判断できます。
したがって、存在しない主キー クエリの場合、データベースは一致するレコードがないと判断し、テーブル全体のスキャンを実行せずにすぐに結果を返します。
11.2 ディスク IO の数を大幅に減らすために、インデックスの構築後に他の最適化措置を講じる必要があるのはなぜですか?
回答: 大きなテーブルには数千万のデータが含まれる可能性があるため、そのインデックス ツリーの高さは 3 ~ 4 層になることがあり、ディスク IO の数は約 4 ~ 5 倍になり、これも非常に時間がかかります。
11.3 データベースのパーティショニングがテーブル全体のスキャンを回避するのに役立つのはなぜですか? パーティションを使用して存在しないデータをクエリする場合、すべてのパーティションの B+ インデックスをクエリしますか?
データベースのパーティション分割を使用する場合、クエリ操作ではすべてのパーティションのスキャンが可能な限り回避されます。クエリ条件にパーティション キー情報が含まれている場合、データベース システムは通常、該当するパーティション上でのみ動作します。ただし、クエリの条件に特定のパーティションを特定できる情報が含まれていない場合は、すべてのパーティションに対してクエリを実行する必要がある場合があります。したがって、存在しないデータに対するクエリの場合、条件にパーティション キーがなければ、すべてのパーティションの B+ インデックスをクエリすることが実際に可能です。
たとえば、範囲パーティション化の条件として日付を使用する場合、テーブルに存在しない日付をクエリする場合、クエリを実行する必要があるパーティションは 1 つだけです。たとえば、最初のパーティションには 2021-1-1~2022-1 が格納されます。 - 1、2 番目のパーティションには 2022-1-1 から 2023-1-1 までのデータが保存されますが、日付が 2022-8-8 のデータをクエリする場合、日付が存在するかどうかに関係なく、2 番目のパーティションのみが保存されます。最初ではなく、質問される必要があります。
11.4 データの概要: 頻繁にクエリされるフィールドを個別に抽出し、ハッシュ値を形成して保存し、クエリを実行する前にクエリ フィールドのハッシュ値を計算して一致するかどうかを確認することを意味します。一致する場合は、mysql データベースにアクセスして、クエリ。持っていない場合は質問しないでください。
はい、正しく理解していますね。データ要約の目的は、生データを直接クエリすることなく、値がデータベースに存在する可能性があるかどうかを判断するための迅速なチェック メカニズムを提供することです。
このアプローチは、ハッシュ関数の特性に基づいています。ハッシュ関数は、入力データ (文字列や数値など) を固定長の数値文字列 (ハッシュ値) に変換します。2 つの入力値のハッシュ値が異なる場合、2 つの入力値は異なる必要があります。ただし、2 つの異なる入力値が同じハッシュ値を生成する場合、これを「ハッシュ衝突」と呼びます。衝突の可能性はありますが、実際には、適切に設計されたハッシュ関数が衝突を引き起こす可能性は非常に低いです。
このシナリオでの使用方法は次のとおりです。
- 頻繁にクエリされるフィールドのハッシュを計算し、別の列またはテーブルに保存します。
- 特定の値をクエリする必要がある場合、最初にその値のハッシュ値が計算されます。
- このハッシュ値が保存されている場所に問い合わせます。ハッシュ値が存在しない場合は、元のデータにも元の値が存在しないことになるため、元のデータをクエリする必要はありません。
- ハッシュが存在する場合は、元のデータをさらにクエリして、実際の一致を判断できます (ハッシュの衝突が発生する可能性があるため)。
この戦略により、一部のシナリオ、特に生データの量が非常に多い場合、またはクエリ操作が非常に頻繁である場合、クエリを大幅に高速化できます。ただし、このアプローチでは、ストレージの複雑さ (ハッシュ値のストレージが追加されるため) と、計算のオーバーヘッド (ハッシュ値を計算する必要があるため) が追加されることにも注意してください。
11.5 ブルームフィルターを使用するこの方法は、特に上記のデータ要約と似ていますか?
おっしゃるとおり、ブルーム フィルターは、前に述べたインデックス サマリーとよく似た機能を果たします。どちらも、不必要なストレージやデータベースの検索を行わずに、データが存在する可能性があるかどうかを迅速に判断するために使用されます。ただし、ブルーム フィルターの特性として、偽陽性 (要素が存在すると誤って信じる) は生成されるが、偽陰性 (要素が存在しないと誤って信じる) は生成されないという点があります。ブルーム フィルターを使用すると、特にビッグ データのシナリオでクエリの効率が大幅に向上します。
11.6 ES などの検索エンジンを使用するとクエリが高速化されるのはなぜですか?
ESの利用ルール
もちろんです。Elasticsearch と Apache Solr はどちらも Lucene 上に構築されており、主に全文検索に使用されますが、ビッグ データの検索および分析ツールとしてもよく使用されます。これらが大規模なデータセットを効率的に処理し、クエリ結果を迅速に返す主な理由は次のとおりです。
-
転置インデックス:
- これが、Lucene (さらには Elasticsearch と Solr) のクエリが非常に高速である主な理由です。簡単に言うと、転置インデックスは、文書から抽出された単語から、その単語が含まれるドキュメントへのマッピングです。ユーザーが単語または語句をクエリする場合、検索エンジンは転置インデックスでその単語のエントリを見つけるだけでよく、各ドキュメントをスキャンすることなく、その単語を含むすべてのドキュメントを迅速に検索できます。
-
シャーディングと並列処理:
- Elasticsearch と Solr はどちらも、複数のノードに分散できるデータの断片 (シャード) への分割をサポートしています。クエリが発行されると、これらのクエリは複数のシャードで並行して実行できるため、クエリ プロセスが大幅に高速化されます。さらに、このシャーディング メカニズムにより、高可用性とフォールト トレランスが実現します。
-
ほぼリアルタイムのインデックス作成:
- データが Elasticsearch または Solr に結合されると、データはすぐにインデックス付けされ、クエリの準備が整います。これにより、データが結合されたばかりであっても、常にクエリ可能になります。
-
圧縮され最適化されたストレージ:
- Lucene はさまざまな手法を使用してインデックスを圧縮し、ストレージ領域を削減し、クエリを高速化します。
-
キャッシュメカニズム:
- Elasticsearch と Solr は両方とも、さまざまなキャッシュ (フィルター キャッシュ、クエリ キャッシュなど) を使用して、繰り返しの計算を減らし、一般的なクエリの応答時間を高速化します。
-
クエリの最適化:
- たとえば、複数の用語をクエリする場合、ツールは結果セットを最も速く絞り込むため、最も一般的でない用語を最初にクエリすることがあります。
したがって、存在しないレコードをクエリすると、転置インデックスやその他の最適化により、検索エンジンはテーブル全体をスキャンしないと、そのレコードが存在しないとすぐに判断できます。
これらの特性により、Elasticsearch と Solr は、大規模なデータセットの高速検索と分析に最適なツールになります。ただし、他のテクノロジーの選択と同様、それらが常に最適なソリューションであるとは限りません。これらのツールを使用するかどうかは、アプリケーションの特定のニーズに基づいて決定する必要があります。
11.7データの削減: 不要になったデータを定期的にアーカイブまたは削除し、テーブルのサイズを管理可能な範囲内に保ちます。セキル商品リストのような定期的なアーカイブに適していますか?
フラッシュ セール製品テーブルの場合、フラッシュ セール アクティビティは特定の時間内に開始および終了するため、この種のテーブルには期限切れのデータや使用されなくなったデータが含まれることがよくあります。このデータを定期的にアーカイブまたは削除することは、確かに良い戦略です。もうアクティブではないが、将来参照する必要がある可能性があるデータ (履歴傾向の分析や監査要件を満たすためなど) をアーカイブし、実際に不要になったデータを削除すると、テーブルの効率が維持され、ストレージのオーバーヘッドが削減されます。