インデックスの性質
インデックスは、MySQL がデータ構造にソートされたデータに効率的にアクセスできるようにするためのものです。
データ構造
二分木赤黒木ハッシュテーブルBツリーB +ツリー
二分木
データベースにインデックスが作成されていない場合、クエリデータは行ごとに比較されてクエリされたデータが取得されるため、クエリ内のデータ量がますます大きくなると、消費される時間が長くなります。
次の図に示すように、Col2はインデックス列として使用され、89のインデックスを取得してCol2 = 89を取得し、データを検索して取得するのに2回しかかかりません。インデックスを使用しない場合は、行ごとに6回比較して取得する必要があります。
Mysqlの最下層は、バイナリツリーデータ構造をインデックスとして使用しません。Col1をインデックス列として使用する場合、次の図にバイナリツリーのデータ構造を示します。データを取得する場合、インデックスを調べても6つのルックアップが必要ですが、効率を上げるための大きな最適化ではありません。端的に言えば、バイナリツリーはこの一方的に増加するデータ列を次のように扱います。索引付けは効率の向上にはあまり役立ちません。
赤黒木
下図の赤黒木のデータ構造は、二分木の片側成長の問題を解決しているようで、3回のクエリで索引6が得られます。しかし、これは最良の解決策ではありません。現在のデータ量は大きくありません。データ量が数百万、数千万に達すると、赤黒木の高さが次第に高くなります。たとえば、treeの高さ= 18の場合、データの一部をクエリします18ディスクIOが必要で、効率はそれほど高くありません。
Bツリー
- 葉ノードの深さは同じです。
- すべてのインデックスは繰り返されません。
- ノードのインデックスは左から右にソートされます
B + Tree(B-Treeバリアント)
Mysqlが使用するデータ構造
- 非リーフノードはデータを格納せず、インデックスのみを格納します。これにより、空き領域を増やしてより多くのインデックスを格納できます。
- リーフノードには、すべてのインデックスフィールドが含まれています。
- リーフノードは、インターバルアクセスのパフォーマンスを向上させるためにポインターで接続されています。
クエリステートメント: 'innodb_page_size'
のような変数を表示非リーフノードは、デフォルトで16384バイト(16KB)を格納できます。たとえば、1つのインデックスが8バイトを占有し、次のインデックスファイルアドレスが6バイトを占有します。16384を8プラス6で割った値は1170です。これは、非リーフノードが約1170のインデックス要素を格納できることを意味します。しかし、葉ノードはデータ要素を格納する必要があり、1KBの割り当てで十分です。つまり、葉ノードは16要素を格納できます。このように、木の高さが3の場合、格納できるデータは1170倍1170倍16倍になり、2000万以上になります。つまり、2,000万を超えるデータディスクioで、必要なデータを3回取得できます。
ハッシュ
- インデックスキーでハッシュ計算を実行して、データの場所を特定します。
- 多くの場合、ハッシュパフォーマンスはB + Treeインデックスよりも効率的です。
- ただし、範囲検索はサポートしていません
MysqlがB-TreeではなくB + Treeを選択するのはなぜですか?
- B + Treeは、B-Treeの非リーフノード上のすべてのデータエレメントをリーフノードに移動し、インデックスエレメントを格納するためにより多くのスペースを解放するため、2,000万のデータが格納されている場合、ツリーの高さは3のみになります。 2,000万のデータを保存します。木の高さは3よりはるかに高いです。
- B + Treeリーフノードにもポインターの関連付けがあります。id> 15などの範囲検索では、15に配置され、ポインターに従って次のデータを取得して、間隔アクセスのパフォーマンスを向上させます。
MyISAMストレージエンジンインデックスの実装(非クラスター化)
InnoDBストレージエンジンインデックスの実装(集計)
セカンダリインデックスセカンダリインデックスの
データ要素は、プライマリキーの値を格納し、プライマリキーIDに従ってテーブルに戻ります。
ジョイントインデックスの格納構造
データ構造可視化URL:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html