MySQL 独立インデックスと共同インデックスの選択

MySQL 独立インデックスと共同インデックスの選択

複数列のインデックスについては、理解が不足していることがよくあります。よくある間違いは、多数の列に独立したインデックスを設定したり、インデックス列の順序を間違えたりすることです。インデックス列の順序の問題については次の記事で説明します。まず、次のテーブル構造を例に、複数の独立したインデックスの場合を見てみましょう。

CREATE TABLEテスト(
  c1 INT、
  c2 INT、
  c3 INT、
  キー(c1)、
  キー(c2)、
  キー(c3)、
);

このインデックス戦略を使用するのは、通常、何らかの権威あるアドバイス (WHERE 条件で使用される条件列にインデックスを追加するなど) の結果です。実際、これは完全に間違っており、せいぜい星 1 つしか付けられません。この方法によるインデックス作成は、実際に最適化されたインデックス作成よりも数桁遅くなります。 3 つ以上の星を持つインデックスを設計できない場合は、WHERE 条件を無視するよりも、行順序の最適化やカバーリング インデックスの作成に重点を置く方がよい場合があります。

カバーリング インデックスとは、クエリ ステートメントの実行をデータ テーブルから読み取ることなく、インデックスからのみ取得できることを意味します。インデックスカバレッジが達成されているとも言えます。 クエリ ステートメントがカバー インデックスの条件を満たす場合、MySQL はインデックスを使用してクエリに必要なデータを返すだけでよいため、インデックスを見つけた後にテーブルに戻る必要がなくなり、I/O が削減され、効率が向上します。 たとえば、covering_index_sample テーブルには共通インデックス idx_key1_key2(key1, key2) があります。 SQL ステートメント「select key2 from coverage_index_sample where key1 = 'keytest';」を使用すると、データ テーブルからデータ行を検索しなくても、カバー インデックスを介してクエリを実行できます。

多くの場合、多くの列に個別のインデックスを作成しても、MySQL のパフォーマンスは向上しません。 MySQL 5.0 以降では、インデックス マージ戦略を使用してこの設計をわずかに最適化できます。このアプローチにより、複数列のインデックスを持つテーブルに対するクエリで、必要な行を見つけるためのインデックスの使用を制限できます。

インデックスのマージは、複数のインデックスに対して条件付きスキャンを個別に実行し、それぞれの結果をマージします(交差/結合)。

以前のバージョンの MySQL では 1 つのインデックスしか使用できなかったため、インデックスのサポートがない場合には MySQL はテーブル全体のスキャンを実行することがよくありました。たとえば、film_actor テーブルには film_id と actor_id のインデックスがありますが、WHERE 条件で両方のインデックスを使用することは適切ではありません。

film_id、actor_id を film_actor から選択します。ここで actor_id = 1 または film_id = 1;

以前のバージョンの MySQL では、次に示すように 2 つのクエリを結合しない限り、このクエリによってテーブル全体がスキャンされます。

film_id、actor_id を film_actor から選択し、 actor_id = 1 を UNION ALL に格納します。 
film_id、actor_id を film_actor から選択します。ここで film_id = 1 かつ actor_id <> 1;

MySQL 5.0 以降では、クエリは両方のインデックスを使用し、最終結果をマージします。このプロセスを実装するには、次の 3 つのアルゴリズムのバリエーションが必要です。

  1. OR条件を使用して結合データを取得する
  2. AND条件を使用して交差データを取得します
  3. 上記の 2 つのステップでデータの共通部分の結合を取ります。

上記は少しわかりにくいですが、実際には、インデックスを使用するために、単一の条件を使用して分散し、すべてのデータを検索してから、データを結合する必要があります。 EXPLAIN を使って確認してみましょう。

EXPLAIN SELECT `film_id`,`actor_id` FROM `film_actor` WHERE `actor_id`=1 OR `film_id`=1

クエリ方法はフルテーブルスキャンですが、最適化のために Extra が使用されていることがわかります。 MySQL は複雑なクエリを処理するときにこの手法を使用するため、Extra にネストされた操作が表示されることがあります。このインデックス マージ戦略は、うまく機能する場合もありますが、多くの場合、インデックスの使用が不適切であることを示していると見なす必要があります。

  1. サーバーが交差インデックス (通常は AND 条件を使用) を使用する場合、通常は、列を結合する個別のインデックスではなく、関連するすべての列を含むインデックスが必要であることを意味します。
  2. サーバーがユニオン インデックス (通常は OR 条件付き) を使用する場合、キャッシュ、並べ替え、およびマージ操作で大量の CPU およびメモリ リソースが消費されることがあります。特に、インデックスにフィルターが常に含まれていない場合は、スキャンによってマージ操作に対して大量の行が返される可能性があります。
  3. オプティマイザーはこれらのコストを負担せず、ランダム ページ読み取りの数を最適化するだけであることに注意してください。これにより、クエリが「安価」になり、テーブル全体のスキャンが実際に遅くなる可能性があります。 CPU とメモリの使用率が高いと同時実行クエリに影響しますが、クエリ ステートメントを個別に実行するとこれらの影響は発生しません。したがって、MySQL 4.1 で行われたように、UNION を使用するようにクエリを書き直す方が最適な場合があります。

EXPLAIN 分析の使用時にインデックスのマージが見られる場合、クエリ ステートメントとテーブル構造をチェックして、それが最適なアプローチであるかどうかを確認する必要があります。 optimizer_switch を使用してインデックスのマージを無効にすることでこれを確認できます。

film_actor のインデックスを結合インデックスに変更し (元の 2 つの独立したインデックス film_id と actor_id を削除)、その効果を確認します。完全なテーブル クエリが回避されていることがわかります。

ALTER TABLE film_actor ADD INDEX `sindex` (`film_id`,`actor_id`);

以上がMySQL独立インデックスとジョイントインデックスの選択の詳細です。MySQL独立インデックスとジョイントインデックスの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • MySQL ジョイントインデックスの使用ルール
  • MySQL ジョイントインデックス(複合インデックス)の実装
  • MySQLジョイントインデックスの左端一致原則の詳細な分析
  • MySQLのジョイントインデックス機能の分析と使用例
  • MySQL ジョイントインデックスの使用例
  • MySQL のジョイントインデックス学習チュートリアル
  • MySQL のインデックス有効条件とインデックス無効条件の結合

<<:  将来的に人気のあるウェブサイトのナビゲーションの方向

>>:  Dockerを使用して開発環境を構築する方法を素早く習得します

推薦する

CentOS7でパーティションのサイズを変更する方法

昨日、ある人のシステムのインストールを手伝ったのですが、自動パーティション分割をクリックするのを忘れ...

Vueは質問応答機能を実装する

1. リクエスト回答インターフェース2. ユーザーの回答が正しいかどうかを判断します。回答が正しい場...

Sublime Text - ブラウザのショートカットキーを設定するための推奨方法

コード効果を異なるブラウザで表示することはよくあることなので、異なるショートカットキーを使用して対応...

Vueプロジェクトのパッケージングと展開の実際のプロセスの記録

目次序文1. 準備 - サーバーとnginxの使用1. サーバーを準備する2. nginxをインスト...

HTML テーブルタグチュートリアル (45): テーブル本体タグ

<tbody> タグは、テーブル本体のスタイルを定義するために使用されます。基本構文 &...

Linux/Mac に MySQL をインストールするときにパスワードを忘れた場合の解決策

序文この記事では主に、Linux/Mac に MySQL をインストールするときにパスワードを忘れた...

docker の実行に必要な権限の分析

Docker を実行するには root 権限が必要です。非 root ユーザーに docker コマ...

sqlite3 から mysql に移行するときに起こりうる問題のコレクション

簡単な説明適切な読者: モバイル開発sqlite3 データを mysql に移行する場合、多くの構文...

Linux のさまざまなロックメカニズムの使用方法と違いについて詳しく説明します

序文:この知識を理解する必要がある人は、すでにプロセス間通信とスレッド間通信の基本的な理解を持ってい...

Ubuntu 16.04 で PostgreSQL の起動を設定する方法

PostgreSQL はコンパイルされインストールされるため、起動時に起動するように設定する必要があ...

Vue3 のレンダリング関数における互換性のない変更の詳細な説明

目次レンダリングAPIの変更レンダリング関数のパラメータレンダリング関数のシグネチャの変更VNode...

分散ロックの原理と3つの実装方法の詳細な説明

現在、ほぼすべての大規模な Web サイトとアプリケーションは分散方式で展開されています。分散シナリ...

a タグにはテキストと画像があります。テキストを非表示にして画像のみを表示するにはどうすればよいでしょうか?

多くの場合、画像を表示する<a>タグのスタイルに遭遇しますが、タグ内にテキストがあり、そ...

SQL実装 LeetCode (176. 2番目に高い給与)

[LeetCode] 176. 2番目に高い給与従業員テーブルから 2 番目に高い給与を取得する ...

MySQLデータベースのタイムアウト設定を構成する方法の例

目次序文1. JDBCタイムアウト設定2. 接続プールのタイムアウト設定3. MyBatisクエリの...