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カスタムカプセル化ボタンコンポーネント

推薦する

フロントエンド HTML+CSS+JS を使用してシンプルな TODOLIST 関数を開発する (メモ帳)

目次1. 簡単な紹介2. スクリーンショットを実行する3. コードの紹介4. まとめ1. 簡単な紹介...

Mysql 5.7.19 無料インストール版 (64 ビット) の設定方法に関する詳細なチュートリアル

公式サイトから mysql-5.7.19-winx64 をダウンロードします。これはシステムの 64...

Linux での MongoDB のインストールに関するチュートリアル

MongoDB はクロスプラットフォームであり、Windows と Linux の両方にインストール...

Nginx と GeoIP モジュールを使用して IP の地域情報を読み取る方法

LinuxにGeoIPをインストールする yum で nginx-module-geoip をインス...

vue3 のストアを使用してスクロール位置を記録する例

目次全体的な効果コンテナのスクロールイベントをリッスンするストア内の構成ページが戻るときのスクロール...

MySQL 8.0.11 のインストールと設定方法のグラフィックチュートリアル MySQL 8.0 の新しいパスワード認証方法

この記事では、参考までにMySQL8.0.11のインストールと設定方法、およびMySQL8.0の新し...

Vuexはセッションストレージデータを結合して、ページを更新するときにデータが失われる問題を解決します

目次序文1. 理由: 2. 解決策のアイデア: 1. ローカル保存方法: 2. 実装手順: 3. 最...

uni-app WeChatアプレット認証ログイン実装手順

目次1. appIDの申請と設定1. appidの取得方法2. AppIDの設定2. 基本的なユーザ...

Ubuntu インストール時にブラックスクリーンが表示される場合の解決策 (3 種類)

私のコンピューターのグラフィック カードは Nvidia グラフィック カードです。再起動後、画面に...

Vueのトランジションとアニメーションの深い理解

1. DOM要素を挿入、更新、または削除するときに、適切な場合は要素にスタイルクラス名を追加します。...

MYSQLの文字セット設定方法(端末の文字セット)の詳しい説明

序文ターミナルを使用してデータベースまたはテーブルを作成するたびに、文字セットが latin1 であ...

Linuxのtimeコマンドの使い方の詳しい説明

1. コマンドの紹介時間は、コマンドの実行に費やされた時間や関連するシステム リソース、その他の情報...

Vue プロジェクトで axios リクエストを使用する方法

目次1. インストール2. カプセル化に問題はない3. ファイルを作成する4. アドレス設定をリクエ...

docker を使用してシンプルな C/C++ プログラムをデプロイする方法

1. まずhello-world.cppファイルを作成しますプログラムコードは次のとおりです。 #i...

js の parseInt() の奇妙な動作の調査と修正

背景: parseInt(0.006) または parseInt(0.0006) は 0 という値を...