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を使用してページ上部のタグを実装する方法の詳細な説明

推薦する

Docker で Spring-boot プロジェクトをデプロイするためのサンプル コード

1. 基本的な Spring-boot クイックスタート1.1 クイックスタート pom.xml は...

Linux MySQL ルートパスワードを忘れた場合の解決方法

MySQL データベースを使用する際、何らかの理由で長期間 MySQL にログインしていない場合、ま...

CSS 命名: BEM、スコープ付き CSS、CSS モジュール、CSS-in-JS の説明

CSS の適用範囲はグローバルです。プロジェクトがどんどん大きくなり、参加する人が増えるにつれて、命...

BFCとは何ですか? CSS 疑似要素を使用してフロートをクリアする方法

BFCコンセプト:ブロック フォーマット コンテキストは、BFC 内の要素を外部の要素から分離する独...

jsを使用して中国語からピンインへの変換の完全な手順を実行します

jsを使用して、中国語をピンインに変換するパッケージを作成しました。倉庫のアドレスはpinyin-p...

CSSは、マウスを線の上に置くと線全体の色を変える効果を実現します。

まとめ:以下のように、CSS で指定した行にマウスを置いたときに行全体の色を変更する方法を示します。...

CSSを使用してファイルアップロードパターンを描画する

以下に示すように、あなたならどのようにそれを達成しますか: 通常、フォントアイコンを使用して中央にプ...

Vue 手書き読み込みアニメーション プロジェクト

ページが応答しない場合、白い画面が表示されないように、読み込みアニメーションを表示するのがユーザーフ...

MySQL 8.0.11 圧縮バージョンを Windows 10 にインストールするための詳細なチュートリアル

最近コンピュータを再インストールした後、最新バージョンのみをインストールするという強迫観念に基づいて...

IE5.0以降のHTCコンポーネントの定義の概要

Microsoft IE 5.0 がリリースされる前は、Web プログラミングにおける最大の課題は、...

HTML での非同期ファイルアップロードの例

コードをコピーコードは次のとおりです。 <form action="/hehe&qu...

Vue3における非親子コンポーネント通信の詳細な説明

目次最初の方法アプリ.vueホーム.vueホームコンテンツ.vueデータの応答性レスポンシブプロパテ...

Webデザインチュートリアル(6):デザインへの情熱を持ち続ける

<br />前の記事:Webデザインチュートリアル(5):Webビジュアルデザイン。 1...

Linux サーバーに Python3 をインストールする 2 つの方法

最初の方法Alibaba Cloud および Baidu Cloud サーバーが利用可能です。 ! ...

Vue+flaskで動画合成機能を実現(ドラッグ&ドロップアップロード)

目次ドラッグアンドドロップアップロードについては以前の記事で書きました。ファイルをアップロードするF...