MySQL InnoDB インデックス拡張の詳細な説明

MySQL InnoDB インデックス拡張の詳細な説明

インデックス拡張: InnoDB は、プライマリ キー列をそのインデックスに追加することで、各セカンダリ インデックスを自動的に拡張します。次のテーブル構造を作成します。

mysql> テーブル t1 を作成します (
  -> i1 INT NOT NULL デフォルト 0,
  -> i2 INT NOT NULL デフォルト 0,
  -> d 日付デフォルト NULL、
  -> 主キー (i1, i2)、
  -> インデックス k_d (d)
  ->) エンジン = InnoDB;

クエリは正常、影響を受けた行は 0 行 (0.14 秒)

テーブル t1 には、列 (​​i1、i2) に定義された主キーがあります。列 (d) にもセカンダリ インデックスが定義されていますが、InnoDB はこのインデックスを拡張し、(d,i1,i2) として扱います。

オプティマイザーは、インデックスの使用方法と使用の有無を決定する際に、拡張セカンダリ インデックスの主キー列を考慮します。これにより、クエリ実行プランの効率が向上し、パフォーマンスが向上します。

オプティマイザーは、ref、range、index_merge インデックス アクセス、ルーズ インデックス スキャン、結合およびソートの最適化、および MIN()/MAX() の最適化に拡張セカンダリ インデックスを使用できます。

次の例は、オプティマイザーが拡張セカンダリ インデックスを使用して実行プランに影響を与え、次のデータをテーブル t1 に挿入するかどうかを示します。

mysql> t1 に値 (1, 1, '1998-01-01')、(1, 2, '1999-01-01')、(1, 3, '2000-01-01')、(1, 4, '2001-01-01') を挿入します。
  ->(1, 5, '2002-01-01')、(2, 1, '1998-01-01')、(2, 2, '1999-01-01')、(2, 3, '2000-01-01')、(2, 4, '2001-01-01')、
  ->(2, 5, '2002-01-01')、(3, 1, '1998-01-01')、(3, 2, '1999-01-01')、(3, 3, '2000-01-01')、(3, 4, '2001-01-01')、
  ->(3, 5, '2002-01-01')、(4, 1, '1998-01-01')、(4, 2, '1999-01-01')、(4, 3, '2000-01-01')、(4, 4, '2001-01-01')、
  ->(4, 5, '2002-01-01')、(5, 1, '1998-01-01')、(5, 2, '1999-01-01')、(5, 3, '2000-01-01')、(5, 4, '2001-01-01')、
  ->(5, 5, '2002-01-01');
クエリは正常、25 行が影響を受けました (0.05 秒)
記録: 25 重複: 0 警告: 0

次のクエリが実行されるとします。

optimizer_switch を 'use_index_extensions=off' に設定します。
i1=3かつd= '2000-01-01'の場合、t1からcount(*)を選択します。

この場合、主キーに列 (i1、i2) が含まれており、クエリが i2 を参照していないため、オプティマイザーは主キーを使用できません。代わりに、オプティマイザは列 (d) のセカンダリ インデックス k_d を使用することができ、実行プランは拡張インデックスが使用されるかどうかによって異なります。

オプティマイザがインデックス拡張を考慮しない場合、インデックスk_dは単に(d)として扱われます。

mysql> SET optimizer_switch = 'use_index_extensions=off';
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

mysql> explain select count(*) from t1 where i1=3 and d= '2000-01-01' \G;
************************** 1. 行 ****************************
      id: 1
 選択タイプ: シンプル
    テーブル: t1
  パーティション: NULL
     タイプ: ref
可能なキー: PRIMARY、k_d
     キー: PRIMARY
   キーの長さ: 4
     参照: 定数
     行数: 5
   フィルター: 20.00
    追加: where の使用
セットに 1 行、警告 1 件 (0.00 秒)

オプティマイザがインデックス拡張を考慮する場合、k_d は (d, i1, i2) であるとみなします。この場合、左端のインデックス プレフィックス (d, i1) を使用して、より適切な実行プランを生成できます。

mysql> SET optimizer_switch = 'use_index_extensions=on';
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

mysql> explain select count(*) from t1 where i1=3 and d= '2000-01-01' \G;
************************** 1. 行 ****************************
      id: 1
 選択タイプ: シンプル
    テーブル: t1
  パーティション: NULL
     タイプ: ref
可能なキー: PRIMARY、k_d
     キー: k_d
   キーの長さ: 8
     参照: const、const
     行数: 1
   フィルター: 100.00
    追加: インデックスの使用
セットに 1 行、警告 1 件 (0.00 秒)

どちらの場合も、 key はオプティマイザーがセカンダリ インデックス k_d を使用することを示していますが、 EXPLAIN 出力には拡張インデックスの使用による次の改善が示されています。

.key_len が 4 バイトから 8 バイトに変更されました。これは、キー検索で d だけでなく列 d と i1 が使用されることを示しています。

キー検索では 1 つのキー列ではなく 2 つのキー列が使用されるため、.ref の値は const から const,const に変わります。

.rows: 5 から 1 に減少し、InnoDB がクエリ結果を生成するために検査する行数が少なくなることを示します。

.Extra 値が、Using where; Using index から Using index に変更されました。つまり、レコードをクエリするには、データ行レコードをクエリするのではなく、インデックスのみを使用する必要があります。

show status を使用すると、拡張インデックスを使用したオプティマイザーと使用しないオプティマイザーの違いを確認できます。

mysql> テーブル t1 をフラッシュします。
クエリは正常、影響を受けた行は 0 行 (0.01 秒)

mysql> ステータスをフラッシュします。
クエリは正常、影響を受けた行は 0 行 (0.03 秒)

上記の flush table および flush status ステートメントは、テーブル キャッシュをクリアし、ステータス統計をクリアするために使用されます。

インデックス拡張を使用しない場合の show status の結果は次のとおりです。

mysql> SET optimizer_switch = 'use_index_extensions=off';
クエリは正常、影響を受けた行は 0 行 (0.01 秒)

mysql> t1 から count(*) を選択します。ここで、i1=3、d= '2000-01-01' です。
+----------+
| カウント(*) |
+----------+
| 1 |
+----------+
セット内の 1 行 (0.00 秒)

mysql> 'handler_read%' のようなステータスを表示します。
+-----------------------+-------+
| 変数名 | 値 |
+-----------------------+-------+
| ハンドラー_read_first | 0 |
| ハンドラー読み取りキー | 1 |
| ハンドラー_read_last | 0 |
| ハンドラー_read_next | 5 |
| ハンドラー_read_prev | 0 |
| ハンドラー読み取り回数 | 0 |
| ハンドラー_read_rnd_next | 0 |
+-----------------------+-------+
セット内の行数は 7 です (0.00 秒)

インデックス拡張を使用すると、show status は次の結果を生成し、handler_read_next の値が 5 から 1 に減少し、このインデックスを使用する方が効率的であることを示します。

mysql> テーブル t1 をフラッシュします。
クエリは正常、影響を受けた行は 0 行 (0.01 秒)

mysql> フラッシュステータス
  -> ;
クエリは正常、影響を受けた行は 0 行 (0.02 秒)

mysql> SET optimizer_switch = 'use_index_extensions=on';
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

mysql> t1 から count(*) を選択します。ここで、i1=3、d= '2000-01-01' です。
+----------+
| カウント(*) |
+----------+
| 1 |
+----------+
セット内の 1 行 (0.00 秒)

mysql> 'handler_read%' のようなステータスを表示します。
+-----------------------+-------+
| 変数名 | 値 |
+-----------------------+-------+
| ハンドラー_read_first | 0 |
| ハンドラー読み取りキー | 1 |
| ハンドラー_read_last | 0 |
| ハンドラー_read_next | 1 |
| ハンドラー_read_prev | 0 |
| ハンドラー読み取り回数 | 0 |
| ハンドラー_read_rnd_next | 0 |
+-----------------------+-------+
セット内の行数は 7 です (0.01 秒)

optimizer_switch システム変数の use_index_extensions フラグを使用すると、オプティマイザは InnoDB テーブルのセカンダリ インデックスの使用方法を決定する際に、プライマリ キー列を考慮から除外できます。デフォルトでは、use_index_extensions は有効になっています。インデックス拡張を無効にするとパフォーマンスが向上するかどうかを確認するには、次のステートメントを実行します。

mysql> SET optimizer_switch = 'use_index_extensions=off';
クエリは正常、影響を受けた行は 0 行 (0.01 秒)

以上がMySQL InnoDBインデックス拡張の詳細な説明です。MySQLインデックス拡張の詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • MySQL InnoDBエンジンのインデックスとストレージ構造の詳細な説明
  • MySQL InnoDBセカンダリインデックスのソート例の詳細な説明
  • MySQL Innodbインデックスの原理の詳細な説明
  • MySQL Innodb インデックス メカニズムの詳細な紹介
  • Mysql Innodb ストレージ エンジン インデックスとアルゴリズム

<<:  Linux zabbix エージェントの展開と設定方法の詳細な説明

>>:  Nginx の動的および静的分離実装ケースのコード分析

推薦する

Linux で誤って削除したメッセージ ファイルを復元する方法

プロセスで使用されていて、誤って削除されたファイルがある場合、それらを回復することができます。プロセ...

Vueフィルターの詳細な説明

<本文> <div id="ルート"> <h2&...

Ubuntu サーバーで MySQL を設定し、リモート接続を実装する方法

サーバー: Ubuntu Server 16.04 LSSクライアント: Ubuntu 16.04 ...

Dockerを使用してOracle_11gをインストールする方法

DockerでOracle_11gをインストールする1. oracle_11gイメージを取得する d...

MySQL バッチ追加および保存メソッドの例

ストレステストにログインする際には、多くの異なるユーザーが必要となり、データベースに新しいデータを追...

HTML テーブルタグチュートリアル (3): 幅と高さの属性 WIDTH、HEIGHT

デフォルトでは、テーブルの幅と高さはコンテンツに応じて自動的に調整されます。テーブルの幅と高さを手動...

Tomcat 初回展開 Web プロジェクト プロセス図

独自のWebプロジェクトをtomcatディレクトリの下のwebappsディレクトリに配置します。 R...

Alibaba Cloud Server Ubuntu 上の Workbench が MySQL に接続できない問題の解決策 (テスト済み)

過去 2 日間、ワークベンチが Alibaba Cloud Server に接続できない問題を解決す...

nginx-ingress-controller ログ永続化ソリューションのソリューション

最近、nginx-ingress-controller のアプリケーションについて説明した公開アカウ...

MySQL 8.0.26 のインストールとアンインストールの完全なステップバイステップの記録

目次序文1. インストール1.公式サイトからダウンロード2. 構成を作成する3. MySQLを初期化...

CSS3で実装されたダイナミックな星空の背景

結果:実装コードhtml <link href='https://fonts.goog...

Linux で完全な Samba サーバーを構築する方法 (CentOS バージョン)

序文smb は、クライアントとサーバー間の Web 接続および情報通信に使用できるプロトコルの名前で...

jsは双方向データバインディング(アクセサ監視)を実現します

この記事の例では、双方向データバインディングを実現するためのjsの具体的なコードを参考までに共有して...

Vueのカスタムイベントコンテンツ配信の詳細な説明

1. これは理解するのが少し複雑なので、原理を注意深く読んで自分で入力していただければ幸いです。 &...

HTMLにおけるbackground-image属性の設定の詳細な説明

写真といえば、まず背景画像が思い浮かびます。私たちの装飾の多くは背景画像を使用して実現されているから...