InnoDB ストレージ エンジン B+ ツリーのツリー高さの導出

目次

1. 基本的な結論: InnoDB ストレージ エンジン B+ ツリーのツリーの高さは 3 ~ 4 層です

2. ストレージエンジンB+ツリー構造の簡易分析

3. 主キーインデックス B+ ツリーの導出

4. InnoDB ページの内部構造の導出

5. InnoDB データファイル導出の分析

6. B+ 樹高の導出と計算に関する一般的な考え方の概要

参考文献、書籍、リンク


1. 基本的な結論: InnoDB ストレージ エンジン B+ ツリーのツリーの高さは 3 ~ 4 層です

InnoDB ストレージ エンジンの B+ ツリーのツリーの高さは通常比較的低く、通常は約 3 ~ 4 レベルです。これは、InnoDB ストレージ エンジンが B+ ツリーの高さを減らすために多くの最適化戦略を使用しているためです。これらには次のものが含まれます。

  1. クラスター化インデックス: InnoDB ストレージ エンジンのクラスター化インデックスは主キーに従って編成されるため、主キーを非クラスター化インデックスに再度格納する必要がなくなり、B+ ツリーの高さが削減されます。
  2. ページ分割: B+ ツリー内のページがいっぱいになると、InnoDB ストレージ エンジンは B+ ツリーのバランスを確保するためにページを分割します。
  3. ページのマージ: B+ ツリー内の一部のリーフ ノードのスペース使用率が低い場合、InnoDB ストレージ エンジンはこれらのノードをより大きなノードにマージして、B+ ツリーの高さを減らします。
  4. アダプティブ ハッシュ インデックス: InnoDB ストレージ エンジンでは、特定のテーブルに対する特定のクエリで非クラスター化インデックスが頻繁に使用される場合、InnoDB はインデックスのハッシュ インデックスを自動的に作成するため、クエリの効率が向上します。

これらの最適化戦略を使用すると、通常、InnoDB ストレージ エンジンの B+ ツリーの高さが小さくなり、データベースのクエリ効率が向上します。

2.ストレージエンジンB+ツリー構造の簡易分析

InnoDB ストレージ エンジンでは、インデックスとデータの保存と編成に B+ ツリー構造が使用されます。一般的なインデックス構成テーブルの構造は次のとおりです。

これは、(id, name) フィールドを含むデータを B+ ツリーに保存する方法です。

主キー ID と次のレベルのノードへのポインタは B+ ツリーの非リーフ ノードに格納され、実際のデータはリーフ ノードに格納されます。隣接するノードは、二重リンク リストを介してリーフ ノード間で接続されます。

ここでの「ノード」は InnoDB の「ページ」です。「ページ」は InnoDB がデータを保存する最小単位で、デフォルトのサイズは 16K です。「ページ」の理解は、他のストレージ モデルにも拡張できます。たとえば、ファイル システムとディスクの両方に独自の最小ストレージ ユニットがあります。ファイル システムの最小ストレージ ユニットは 4K ですが、ディスク上の最小ストレージ ユニットはは512バイトです。InnoDB は、次のデータ関係を通じてディスクからデータを読み込みます。

InnoDB の「ページ」サイズから、テーブルがデータを保存するかどうかに関係なく、テーブルは InnoDB 内で少なくとも 16K のスペースを占有し、テーブルがどれほど大きくても、InnoDB で使用されるスペースは次の整数倍でなければならないと推測できます16

3. 主キーインデックス B+ ツリーの導出

ツリー高さ = 1 の場合:この時点で、B+ ツリーには 1 つのノード (リーフ ノードでもあるルート ノード) のみがあり、すべてのデータはこのノードに格納されます。単一行のデータサイズが 1k であると仮定します。ノードが保存できるデータ行の数 = ノード容量/単一行データ サイズ = 16K/1K = 16 行のデータ となります

木の高さ = 2 の場合:このように、B+ ツリーにはルート ノードとリーフ ノードがあり、ルート ノードには主キーとポインタがあり、リーフ ノードにはデータが格納されます。

各リーフ ノードに保存できるデータ行数は、上記のように計算されます = ノード容量 / 1 行データ サイズ = 16K/1K = 16 行のデータ。ルートノードに格納できるポインタ数 = ノード容量 / (主キー長 + ポインタ長) = 16K / (8byte + 6byte) = 1170 となります。(注: ポインタの長さは 6 バイトに固定されています。主キーは bigint 型を使用し、長さは 8 バイトであると仮定しています)

したがって、ツリー高さが 2 の B+ ツリーの場合、格納できるデータ行数 = 1 つのリーフ ノードに格納されるデータ行数 X ルート ノード ポインタの数 = 16 X 1170 = 18720 となります。

木の高さ = 3 の場合:このとき、B+ ツリーにはルート ノード、非葉ノード、葉ノードが含まれます。

上記の計算方法より、木の高さ=3の場合、格納できる行数=1つの葉ノードに格納されるデータ行数×非葉ノードポインタ数×ルートノードポインタ数となります。 = 16

したがって、推論すると、データの1行のサイズがSバイト、ツリーの高さがHの場合、bigint型の主キーB + ツリーインデックスに格納できる行数Nが等しいという結論になります。に:

式に従って計算すると、木の高さが 4 の場合、2,000 億行を超えるデータを保存できます。この種のデータ容量はほとんどのアプリケーションのニーズを満たすことができるため、ほとんどのアプリケーションでは、B+ ツリーの高さ 3 または 4 でデータ ストレージのニーズを満たすことができると言えます。B+ ツリーの高いファンアウトと低いツリー高により、主キー クエリのパフォーマンスも大幅に向上します。

4. InnoDB ページの内部構造の導出

「ページ」のスペースはユーザー データの保存に使用されると想定されていますが、実際の「ページ」にはユーザー データの保存に加えて、いくつかの補助情報を保存するためのスペースも確保されています。完全な「ページ」は次の 7 つの部分で構成されます。

ユーザー レコードは、「ページ」内で最も多くのスペースを占めます。これは、ユーザー データ レコードの保存に使用されるスペースです。Infimum + Supremum Records、Free Space、および Page Directory によって使用される非常に小さなスペースを無視した場合、データ レコードの保存に使用されるスペースは、おおよそ次のように考えられます: ページ容量 - フィル ヘッダー - ページ ヘッダー - フィル トレーラー = 16384 - 38 - 56 - 8 = 16282 バイト。この結果に基づいて、式を更新します。

B+ ツリーが格納できるデータ行数の推論と計算を通じて、B+ ツリーの木の高さは一般に 1 ~ 4 層であることが側面から証明されます

5. InnoDB データファイル導出の分析

InnoDB ページの上記の構造分析を通じて、ページ ヘッダー部分にページ レベル フィールドがあり、インデックス ツリー全体における現在のページの位置を示していることがわかります。

  • 現在のページがツリーのリーフ ノードにある場合、ページ レベル = 0
  • 現在のページがリーフ ノードの 1 つ上のレベルにある場合、ページ レベル=1
  • 同様に、ツリーに 3 つのレベルがある場合、リーフ ノード ページ レベル = 0、非リーフ ノード ページ レベル = 1、ルート ノード ページ レベル = 2 となります。
  • ツリーの高さがページ レベルから推測される場合、ツリーの高さ = ルート ノードのページ レベル + 1 であることがわかります。

したがって、主キー インデックスのルート ノードのページ レベル値が InnoDB データ ファイルで見つかる場合、主キー インデックス ツリーのツリーの高さを計算できます

InnoDB データ ファイル内の主キー インデックスのページ番号を検索します。

InnoDB データ ファイル内の主キー インデックスのルート ノードを解析するには、まずデータ ファイル内の主キー インデックスの場所を見つける必要があります。MySQL に組み込まれている information_schema.INNODB_SYS_INDEXES および information_schema.INNODB_SYS_TABLES には、主キー インデックスが配置されているページ番号に関する情報が含まれています。

SELECT
b.name as tableName, a.name as indexName, index_id, type, a.space, a.PAGE_NO
FROM
information_schema.INNODB_SYS_INDEXES a,
information_schema.INNODB_SYS_TABLES b
WHERE
a.table_id = b.table_id AND a.space <> 0 and b.name ='dbt3/lineitem' and a.name='PRIMARY';

この SQL を通じてクエリされた lineitem テーブルの主キー インデックスのページ番号は 3 です。実際、InnoDB 内のすべてのテーブルの主キー インデックスのページ番号は 3 であり、他のテーブルをクエリすることで確認できます。

データファイル内のページレベルの位置を計算します。

各ページのサイズ (16K) により、データ ファイル内で主キー インデックスが配置されているページを見つけることができます。データ ファイル内のページ レベル フィールドの場所をさらに検索します。

InnoDB ページの構造特性によると、Fil ヘッダー部分が最初の 38 バイトを占め、ページ レベル フィールドがページ ヘッダー部分の 26 バイトのオフセットにあり、2 バイトを占めていることがわかります。したがって、ページ全体におけるページ レベル フィールドの位置が 64 バイト オフセットの位置であると結論付けることができます。

データ ファイル (lineitem.idb ファイル) のページ レベル フィールドを解析する場合、スキップする必要があるオフセット = 3 * 16384 (16K) + 38+ 26 = 49152+64=49216。ページ レベルの値は、オフセットの次の 2 バイトにあります。lineitem.idb ファイルの Page Level=2、つまりツリーの高さ=Page Level+1=3 層が解析されていることがわかります

6. B+ 樹高の導出と計算に関する一般的な考え方の概要

InnoDB ストレージ エンジンで B+ ツリーを使用する場合、B+ ツリーの高さは通常、次の導出によって計算できます。

  1. まず、B+ ツリーのノード サイズと、各ノードが収容できるインデックス アイテムの数を知る必要があります。これは、ページ サイズ、ノード ヘッダー サイズ、InnoDB ストレージ エンジンのインデックス アイテム サイズなどのパラメーターによって決定できます。
  2. 次に、B+ ツリーの定義に従って、ルート ノード、中間ノード、および葉ノードのインデックス アイテムの最小数を計算できます。通常、ルート ノードと中間ノードには少なくとも 2 つの子ノードがあり、リーフ ノードには通常、最大数のインデックス エントリがあります。
  3. 次に、B+ ツリーの構造と定義に基づいて、ルート ノード、中間ノード、およびリーフ ノードが収容できるインデックス アイテムの最大数を計算できます。中間ノードとリーフ ノードの場合、この数はノード サイズと各インデックス エントリのサイズによって異なります。
  4. 最後に、B+ ツリーの定義とインデックス エントリの最小/最大数を使用して、B+ ツリーの高さを計算できます。InnoDB ストレージ エンジンでは、クエリのパフォーマンスを向上させ、ディスク IO オーバーヘッドを削減するために、通常、B+ ツリーの高さを最小値に近づけようとします。

これは B+ ツリーの高さを計算する 1 つの方法にすぎないことに注意してください。ストレージ エンジンやデータベースが異なれば、使用する最適化戦略も異なる可能性があるため、計算結果は異なる場合があります。同時に、B+ ツリーの高さだけがクエリのパフォーマンスに影響を与える要因ではなく、インデックスの選択性やデータ分散などの要因も考慮する必要があります。

参考文献、書籍、リンク

1.「MySQL Technology Insider: InnoDB Storage Engine」(第 2 版): MySQL Technology Insider (Douban)

2.《InnoDB の内部: InnoDB ストレージ エンジン》:MySQL :: MySQL 8.0 リファレンス マニュアル :: 15 InnoDB ストレージ エンジン

3.《InnoDB: 究極ガイド》:https://www.percona.com/blog/2018/06/05/innodb-the-ultimate-guide/

4.《InnoDB ストレージ エンジンの内部》:https://mariadb.com/kb/en/innodb-storage-engine-internals/

5. InnoDB データページ構造

おすすめ

転載: blog.csdn.net/xiaofeng10330111/article/details/130464048