MySQL btree インデックスとハッシュ インデックスの違い

MySQL btree インデックスとハッシュ インデックスの違い

MySQL では、ほとんどのインデックス (PRIMARY KEY、UNIQUE、INDEX、FULLTEXT など) は BTREE に格納されますが、メモリ エンジンを使用する場合は、BTREE インデックスまたは HASH インデックスを選択できます。2 つの異なるタイプのインデックスには、使用範囲が異なります。

  • B ツリー インデックスには、範囲検索とプレフィックス検索を実行する機能があります。N 個のノードを持つ B ツリーの場合、レコードを取得する複雑さは O(LogN) です。バイナリ検索と同等です。
  • ハッシュインデックスは等価検索にのみ使用できますが、ハッシュテーブルがどれだけ大きくても、検索の複雑さは O(1) です。

明らかに、値が大きく異なり、主な検索が等しい値(=、<、>、in)である場合、ハッシュインデックスは検索の複雑さが O(1) であるため、より効率的な選択肢となります。
値間の差が比較的小さく、範囲検索が主な焦点である場合は、範囲検索をサポートしている B ツリーの方が適しています。

1. ハッシュインデックス

保存アドレスはハッシュ関数を使用して計算されるため、取得時にBtreeのようにルートノードからトラバースしてレベルごとに検索する必要はありません。

ハッシュ インデックスの特殊な構造により、検索効率が非常に高くなります。ルート ノードからブランチ ノード、そして最終的にページ ノードまで複数の IO アクセスを必要とする B ツリー インデックスとは異なり、インデックス検索は 1 回で済みます。そのため、ハッシュ インデックスのクエリ効率は B ツリー インデックスよりもはるかに高くなります。

多くの人が再び疑問に思うかもしれません。ハッシュ インデックスの効率は B-Tree よりもはるかに高いのに、なぜ B-Tree インデックスの代わりにハッシュ インデックスを使用しないのでしょうか。すべての物事には2つの側面があり、ハッシュ インデックスでも同じことが言えます。ハッシュ インデックスは非常に効率的ですが、その特殊性により多くの制限や欠点もあります。主なものは次のとおりです。

(1)ハッシュインデックスは「=」、「IN」、「<=>」クエリのみを満たすことができ、範囲クエリには使用できません(範囲クエリは低速です)。

ハッシュインデックスはハッシュ演算後のハッシュ値を比較するため、対応するハッシュアルゴリズムによって処理された後のハッシュ値の大小関係がハッシュ演算前と全く同じであることを保証できないため、等値フィルタリングにのみ使用でき、範囲ベースのフィルタリングには使用できません。

(2)ハッシュインデックスはデータのソート操作を回避するために使用することはできません。

ハッシュ インデックスにはハッシュ計算後のハッシュ値が格納され、ハッシュ値のサイズ関係はハッシュ操作前のキー値と必ずしも正確に同じではないため、データベースはインデックス データを使用してソート操作を回避することはできません。

(3)ハッシュインデックスは部分インデックスキーを使用してクエリすることはできません。

複合インデックスの場合、ハッシュ インデックスはハッシュ値を個別に計算するのではなく、複合インデックス キーを結合してハッシュ値を計算します。したがって、複合インデックスの最初の 1 つまたは複数のインデックス キーをクエリする場合、ハッシュ インデックスは使用できません。

(4)ハッシュインデックスは、いつでもテーブルスキャンを回避することはできません。

ご存知のように、ハッシュ インデックスは、インデックス キーをハッシュした後、ハッシュ操作の結果のハッシュ値と対応する行ポインタ情報を格納するテーブルです。異なるインデックス キーは同じハッシュ値を持つため、特定のハッシュ キー値を満たすレコードの数を取得しても、ハッシュ インデックスから直接クエリを完了することはできません。テーブル内の実際のデータにアクセスして対応する比較を実行し、対応する結果を取得する必要があります。

(5)ハッシュ値が多数等しい場合、ハッシュインデックスのパフォーマンスは必ずしもBツリーインデックスのパフォーマンスよりも高いとは限りません。

選択性の低いインデックス キーの場合、ハッシュ インデックスを作成すると、大量のレコード ポインター情報が同じハッシュ値に格納され、それに関連付けられます。これにより、特定のレコードを見つけるのが非常に面倒になり、複数のテーブル データ アクセスが無駄になり、全体的なパフォーマンスが低下します。

2. B+ツリー

  • b+ツリーの探索プロセス

図に示すように、データ項目 29 を検索する場合、最初にディスク ブロック 1 がディスクからメモリにロードされます。このとき、IO が発生します。メモリ内でバイナリ検索を使用して、29 が 17 と 35 の間にあることを判別します。ディスク ブロック 1 の P2 ポインターはロックされています。メモリ時間は非常に短いため (ディスク IO と比較して) 無視できます。ディスク ブロック 3 は、ディスク ブロック 1 の P2 ポインターのディスク アドレスを介してディスクからメモリにロードされます。2 番目の IO が発生します。29 は 26 と 30 の間にあります。ディスク ブロック 3 の P2 ポインターはロックされています。ディスク ブロック 8 は、ポインターを介してメモリにロードされます。3 番目の IO が発生します。同時に、メモリ内でバイナリ検索を実行して 29 を見つけ、クエリが終了します。合計 3 つの IO が実行されます。実際には、3 層の B+ ツリーは数百万のデータを表すことができます。数百万のデータの検索に 3 つの IO しか必要ない場合、パフォーマンスは大幅に向上します。インデックスがない場合、各データ項目に IO が必要になり、合計で数百万の IO が必要になりますが、これは明らかに非常にコストがかかります。

  • B+ツリーのプロパティ

1. インデックス フィールドはできるだけ小さくする必要があります。

以上の分析から、IO回数はb+numberの高さhに依存することがわかります。現在のデータテーブルのデータがNで、各ディスクブロックのデータ項目数がmであると仮定すると、h=㏒(m+1)Nとなります。データ量Nが一定の場合、mが大きいほどhは小さくなり、m = ディスクブロックサイズ/データ項目サイズとなります。ディスクブロックサイズはデータページのサイズで、固定されています。データ項目が占めるスペースが小さく、データ項目数が多いほど、ツリーの高さは低くなります。このため、各データ項目、つまりインデックス フィールドは、できるだけ小さくする必要があります。たとえば、int は 4 バイトを占めますが、これは bigint の 8 バイトの半分です。このため、b+ ツリーでは、実際のデータを内部ノードではなくリーフ ノードに配置する必要があります。内部ノードに配置すると、ディスク ブロックのデータ項目が大幅に減少し、ツリーの高さが増加します。データ項目が 1 に等しい場合、線形リストに退化します。

2. インデックスの最も左のマッチング機能(つまり、左から右へのマッチング):

b+ツリーのデータ項目が(名前、年齢、性別)などの複合データ構造である場合、b+ツリーは左から右の順に検索ツリーを構築します。たとえば、(張三、20、F)などのデータが取得されると、b+ツリーは最初に名前を比較して次の検索方向を決定します。名前が同じ場合は、年齢と性別が順番に比較され、最終的に取得されたデータを取得します。ただし、(20、F)などの名前のないデータが来ると、b+ツリーは次にどのノードをチェックすればよいかわかりません。これは、名前が検索ツリーを構築するときの最初の比較要素であり、次にどこを照会するかを知るために最初に名前に基づいて検索する必要があるためです。たとえば、(Zhang San, F) のようなデータを取得する場合、b+ ツリーは名前を使用して検索方向を指定できますが、次のフィールド age が欠落しているため、名前が Zhang San と同じデータのみを検索し、その後、性別が F のデータと一致させます。これは非常に重要なプロパティであり、インデックスの最も左の一致機能です。

上記は、MySQL btree インデックスとハッシュ インデックスの違いに関する詳細な内容です。MySQL btree インデックスとハッシュ インデックスの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • MySQL ハッシュインデックスと B ツリーインデックスの違い
  • MySQL データベース インデックスが B+ ツリーの使用を選択するのはなぜですか?
  • MySQL 最適化における B ツリー インデックスの知識ポイントのまとめ
  • MySQL Bツリーインデックスとインデックス最適化の概要についての簡単な説明
  • MySQL innodb B+ツリーの高さを取得する方法
  • MySQL における Btree インデックスとハッシュ インデックスの比較
  • MySQL B-Tree インデックスの簡単な分析

<<:  deepin20 で NVIDIA クローズドソース ドライバーをインストールするための詳細な手順

>>:  Vueカスタムカプセル化ボタンコンポーネント

推薦する

Docker管理に関する断片的な知識のまとめ

目次1. 概要2. 応用例2.1、Docker コンテナ分離名前空間2.2. Docker のフリー...

4種類のMySQL接続とマルチテーブルクエリの詳細な説明

目次MySQL 内部結合、左結合、右結合、外部結合、複数テーブルクエリビルド環境: 1. 内なる慈恩...

画像の盗難を防ぐために Nginx で Referer を設定する方法

サーバーの画像が他のウェブサイトからホットリンクされると、サーバーの帯域幅とアクセス速度に影響します...

Word のコンテンツを Web サイトのエディターに直接コピーすることはお勧めしません。

<br />質問: Word のコンテンツを Web サイトのエディターに直接コピーする...

Vue実装のカウンターケース

この記事では、カウンター表示を実現するためのVueの具体的なコードを例として紹介します。具体的な内容...

CSS の新機能には、コントロールページの再描画と再配置の問題が含まれています

新しい CSS プロパティ contain を紹介する前に、読者はページの再描画と再配置が何であるか...

MySQL における「:=」と「=」の違いの簡単な分析

=設定および更新の場合にのみ、:= と同じ効果、つまり代入効果があり、それ以外の場合は等号の効果があ...

Linux プロセス管理ツール スーパーバイザーのインストールと設定のチュートリアル

環境: CentOS 7公式ドキュメント: http://supervisord.org/インストー...

シェルスクリプトを使用して CentOS7 に python3.8 環境をインストールする (推奨)

ワンクリック実行仮想マシンに Python 3.8 をインストールするには、ネットワーク アダプター...

Nginx 構成 SSL および WSS 手順の紹介

目次序文1. Nginxのインストール1. Nginxをダウンロードする2. 依存関係をインストール...

NginxにLuaモジュールを追加する方法

luaをインストールする http://luajit.org/download/LuaJIT-2.0...

MySQL 圧縮の使用シナリオとソリューション

導入圧縮トランスポート プロトコル、圧縮列ソリューション、圧縮テーブル ソリューションなど、MySQ...

JavaScript におけるイベント バブリング メカニズムの詳細な分析

バブリングとは何ですか? DOM イベント フローには、イベント キャプチャ ステージ、ターゲット ...

CentOS7 64ビットインストールmysqlグラフィックチュートリアル

MySQL をインストールするための前提条件: CentOS 7 64 ビットをインストールし、Ce...

MySQLとRedisでセカンダリキャッシュを実装する方法の詳細な説明

Redis の紹介Redis は完全にオープンソースで無料であり、BSD プロトコルに準拠しており、...