MySQLが基礎データ構造としてB+ツリーを使用する理由

MySQLが基礎データ構造としてB+ツリーを使用する理由

MySQL の基盤となるデータ構造が B+ ツリーであることは誰もが知っていますが、ではなぜ赤黒ツリーやその他のデータ構造を使用しないのでしょうか?

赤黒木は自己バランス型二分探索木です。Java8 のハッシュマップは、クエリ効率を最適化するために赤黒木を使用しています。赤黒木のクエリ効率は依然として比較的高いことがわかります。しかし、なぜ MySQL は最下層で赤黒木ではなく B+ 木を使用するのでしょうか?

次の図は、赤黒木を 1、2、3、4、5、6 に順番に挿入した後の状況を示しています。

次に、上記の赤黒ツリーに 7 を挿入します。

赤黒木は自己バランスが取れているものの、全体としては依然としてデータ全体が木の右側に偏っていることがわかります。さらにデータが追加されると、数百万または数千万のデータが追加された後、木のレベルは非常に高くなります。クエリを実行するときに、各追加レイヤーにさらに 1 つの IO が必要になります。ツリー レベルの数が増えると、検索効率が非常に低くなります。このとき、なぜもっとバランスの取れた AVL ツリーを使用しないのかと疑問に思う人もいるかもしれません。

1、2、3、4、5、6、7 を一度に挿入した後の AVL ツリーは次のようになります。

確かに見た目はずっと良くなり、ツリー レイヤーの数も減りましたが、AVL では根本的な問題は解決されていません。データ量が数百万、数千万に達すると、ツリー レイヤーの数はまだ比較的多くなります。AVL ツリーのバランスを維持するためのコストは言うまでもなく、AVL ツリー レイヤーの数だけでは要件を満たすことができません。

では、データ量が数百万、数千万、あるいはそれ以上に達したときに、レイヤーの数を少なく抑えることができるデータ構造とはどのようなものでしょうか?当然ですが、レイヤーの数を減らしたい場合は、各レイヤーにより多くのデータを保存する必要があります。バイナリ ツリーがどれだけバランスが取れていても、各ノードには 2 つのフォークしか存在できません。各レイヤーのデータ量はデータ構造によって制限されるため、バイナリ ツリーから選択することはできません。このとき、B ツリーの利点が反映されます。B ツリーの各ノードには複数の要素を格納でき、各要素にはフォークを設定できます。次の図は、B ツリーの各ノードに最大 3 つの要素を格納できることを示しています。

ツリーレベルが 2 レベルに削減されていることがわかります。各ノードに一度に格納できる要素の最大数が十分に大きければ、データ量が数千万に達したとしても、ツリーレベルを許容範囲内に抑えることができます。

しかし、B ツリーには別の問題があります。次の図は、B ツリー レベルが 3 レベルに達した場合の状況を示しています。

ここで要素 5 ~ 10 を取り出す必要がある場合、レイヤーごとのクエリで要素 5 を見つけ、他の要素がこのノードにないことがわかったら、ローカル順序トラバーサルで他の要素をクエリする必要があります。7 を見つけた後、同じ操作を実行して 8、9、10 を見つける必要があります。これにより IO 回数が増えるため、B+ ツリーが発生します。

B+ ツリーは、主に次の 2 つの側面から B ツリーを最適化したものです。

最初の最適化は、各リーフ ノード間に、隣接するノードを指す双方向ポインターを追加することです。これにより、前述の範囲クエリの問題が解決されます。範囲クエリが複数のノードにまたがる場合、ローカルの順序どおりのトラバーサルを必要とせずに、この双方向ポインターを通じて隣接するノードをすばやく見つけることができるため、IO 回数が削減されます。次の図は B+ ツリーを示しています。

しかし、探している要素がリーフノードにない場合はどうなるでしょうか?心配しないでください。B+ ツリーのもう 1 つの最適化は、リーフ ノードにツリーのすべての要素が含まれることです。 B+ ツリーの非リーフ ノードには、要素のデータやポインターは格納されなくなり、クエリを簡単に実行できるように完全な B+ ツリーを形成するための冗長インデックスとしてのみ機能します。上図の要素 15 は、非リーフ ノードだけでなく、リーフ ノードにも存在することがわかります。この設計では、多くの冗長なインデックスが必要になりますが、範囲クエリを実行するときに非リーフ ノードを上方向に検索する必要がなくなります。さらに、各レベルに格納できるインデックスの数が増えるため、データベースは IO を実行するたびに、より多くのインデックス要素をクエリできます。結局のところ、通常の状況では、データが占めるスペースは、インデックスが占めるスペースよりもはるかに大きくなります。 (InnoDB エンジンと MyISAM エンジンはどちらも B+ ツリーを使用しますが、InnoDB のクラスター化インデックスとデータは一緒に保存されるのに対し、MyISAM はクラスター化インデックスと対応するデータ ポインターを一緒に保存し、インデックスとデータは別々に保存されることに注意してください。MyISAM エンジンの B+ ツリーも、リーフ ノードにデータ ポインターのみを保存します。)

上記の分析から、MySQL の基盤レイヤーとして B+ ツリーが選択された理由は、IO 操作の数を減らすためであることがわかります。では、極端に進んでハッシュを使用してデータやインデックスを保存しないのはなぜでしょうか?実際、MySQL はハッシュ タイプのインデックスをサポートしています。

ただし、ハッシュ インデックスはハッシュ コードを格納するものであり、格納順序はインデックス列の値のサイズとは関係がないため、通常は使用されません。したがって、ハッシュ インデックスは正確な検索を実行する場合にのみ有効であり、範囲クエリでは完全なテーブル スキャンが実行されます。同時に、テーブル内のデータ量が非常に多い場合、ハッシュ衝突の数が増加し、単一の検索の効率が B+ ツリーよりも高くならない可能性があります。

簡単にまとめると、他のツリーと比較して、B+ツリーの各ノードはより多くの要素を格納できるため、クエリに必要なIO回数を大幅に削減できます。データやポインタを格納しない非リーフノードの設計により、各ノードに格納される要素の数を増やすことができ、リーフノードの双方向ポインタにより範囲クエリの効率を向上させることができます。

これで、MySQL が基礎データ構造として B+ ツリーを使用する理由に関するこの記事は終了です。MySQL B+ ツリーの詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL データベース インデックスが B+ ツリーの使用を選択するのはなぜですか?
  • MySQL でインデックス構造として B+ ツリーを使用する利点は何ですか?
  • MySQL で B+ ツリー インデックスを使用する利点は何ですか?
  • MySQLのインデックスシステムがB+ツリーを使用する理由の分析
  • MySQL の B ツリー インデックスと B+​​ ツリー インデックスの違いの詳細な説明
  • MySQL B+ツリーインデックスとハッシュインデックスの詳細な説明
  • MySQL インデックス データ構造が B+ ツリーを使用する理由を理解するための記事

<<:  IE9 のネイティブ ページ互換性の問題に対する解決策についての簡単な説明

>>:  Vue+elementを使用してページ上部のタグを実装する方法の詳細な説明

推薦する

Vue 名前付きスロットの基本的な使用例

序文名前付きスロットは、スロット内の「name」属性を使用して要素にバインドされます。知らせ: 1....

Docker Swarmの概念と使用法の詳細な説明

Docker Swarm は、Docker によって開発されたコンテナ クラスター管理サービスです。...

Linux 環境変数の設定方法のまとめ (.bash_profile と .bashrc の違い)

Linux では、アプリケーションをダウンロードしてインストールすると、起動時にアプリケーション名...

MySQLは「order by」がどのように機能するかを簡単に理解します

並べ替えの場合、order by は非常に頻繁に使用するキーワードです。インデックスに関するこれまで...

react-beautiful-dnd を使用してリスト間のドラッグ アンド ドロップを実装する

目次react-beautiful-dndを選ぶ理由基本的な使い方基本概念使い方使用中に発生した問題...

MySQL インデックスの原理と最適化の詳細な説明

序文この記事は Meituan の大物によって書かれました。とても素晴らしいので、皆さんと共有したい...

HTML で 2 つの div タグの間に垂直線を描く方法

最近、インターフェースを描画しているときに、インターフェースに垂直線を描画し、この垂直線の高さが親 ...

JavaScript イベント委任の原則

目次1. イベント委任とは何ですか? 2. イベント委任の原則3. イベント委託の役割1. イベント...

Vueコンポーネント登録方法の解釈

目次概要1. グローバル登録2. 現地登録3. モジュールシステムへのローカル登録概要コンポーネント...

MySQL 5.7.20 解凍版のインストールとルートパスワードの変更に関するチュートリアル

1. MySQL アーカイブ (解凍版) をダウンロードするURL: https://downloa...

MySQLデータクエリが多すぎるとOOMが発生するかどうかについての簡単な議論

目次サーバー層でのフルテーブルスキャンの影響InnoDB におけるフルテーブルスキャンの影響Inno...

MySQL の InnoDB ストレージ ファイルの詳細な説明

物理的に言えば、InnoDB テーブルは、共有テーブルスペース ファイル (ibdata1)、排他テ...

CSS セレクターの重みの理解(個人テスト)

コードをコピーコードは次のとおりです。 <スタイル タイプ="text/css&qu...

WeChat公式アカウントでReactプロジェクトを実行する方法

目次1. a タグを使用して PDF をプレビューまたはダウンロードします。書き方は、携帯電話でクリ...

Vue cli開発に基づく外部コンポーネントVantのデフォルトスタイルの変更の詳細な説明

目次序文1. 少ない2. コンポーネントをインポートする3. 設定ファイルを変更するステップ1: l...