1.データページの構造
データページで表される16KBのストレージスペースは複数の部分に分割できます。異なる部分は異なる機能を持ちます。各部分は図のようになり
ます。InnoDBデータページのストレージスペースは大きく7つの部分に分割されます。バイト数一部の部分が占めるバイト数は定かであり、一部の部分が占めるバイト数は定かではありません。
レコードの保存
ページの7つのコンポーネントのうち、独自に保存されたレコードは、指定した行形式で保存されます。ユーザーレコード部。ただし、ページが最初に生成されたときは、ユーザーレコードの部分はありませんでした。レコードを挿入するたびに、空き領域の部分、つまり未使用のストレージスペースからレコードサイズのスペースを申請し、それをユーザーレコード部分。空き領域部分のすべてのスペースがユーザーレコード部分に置き換えられると、ページが使い果たされることを意味します。新しいレコードが挿入されている場合は、新しいページを申請する必要があります。以下に示すように:
ヘッダー情報を記録する
名前 | サイズ(ビット) | 説明 |
---|---|---|
予約ビット1 | 1 | 使用しなかった |
予約スロット2 | 1 | 使用しなかった |
delete_mask | 1 | レコードが削除されたかどうかをマークします |
min_rec_mask | 1 | このマークは、B+ツリーの各レベルの非リーフノードの最小レコードに追加されます |
n_owned | 4 | 現在のレコードが所有するレコードの数を示します |
heap_no | 13 | レコードヒープに現在記録されている位置情報を示します |
record_type | 3 | 現在のレコードのタイプを示します。0は通常のレコードを表し、1はB +ツリーの非リーフノードレコードを表し、2は最小のレコードを表し、3は最大のレコードを表します。 |
next_record | 16 | 次のレコードの相対位置を示します |
例:テーブルを作成する
CREATE TABLE page_demo(
c1 INT,
c2 INT,
c3 VARCHAR(10000),
PRIMARY KEY (c1)
) CHARSET=ascii ROW_FORMAT=Compact;
INSERT INTO page_demo VALUES(1, 100, 'aaaa'), (2, 200, 'bbbb'), (3, 300, 'cccc'),(4, 400, 'dddd');
ユーザーレコードに各レコードを保存する際にギャップはありません。ここでは、見やすいように各レコードを線で囲んでいます。
- 属性delete_mask
は、現在のレコードが削除されているかどうかを示し、1つのバイナリビットを占有します。値が0の場合はレコードが削除されていないことを意味し、1の場合はレコードが削除されていることを意味します。
これらの削除されたレコードがディスクからすぐに削除されない理由は、削除後にディスク上の他のレコードを再配置するのにパフォーマンスの消費がかかるためです。これは単なる削除マークであり、削除されたすべてのレコードはいわゆるガベージリンクリストになります。このリンクリスト内のレコードが占めるスペースは、いわゆる再利用可能スペースと呼ばれます。後で新しいレコードがテーブルに挿入されると、これらの削除されたレコードが占めるストレージスペースが上書きされる可能性があります。
- heap_no
属性は、このページでの現在のレコードの場所を示します
- このページに挿入した4つのレコードの位置は次のとおりです:2、3、4、5
- InnoDBは、各ページに2つのレコードを自動的に追加します。これらの2つのレコードは自分で挿入しないため、疑似レコードまたは仮想レコード(0、1)と呼ばれることもあります。これら2つの疑似レコードの1つは最小のレコードを表し、もう1つは最大のレコードを表します。
- 完全なレコードの場合、レコードのサイズを比較することは、主キーのサイズを比較することです。たとえば、挿入する4行のレコードの主キー値は1、2、3、4です。これは、これら4つのレコードのサイズが小さいものから大きいものへと順番に増加することを意味します。
- ダミーレコードまたはダミーレコードは、5バイトのレコードヘッダー情報と8バイトのサイズの固定部分で構成されます。
これらの2つのレコードは、独自に定義したレコードではないため、ページの[ユーザーレコード]セクションには保存されず、Infimum+Supremumというセクションに別々に配置されます。
- record_type
属性は、現在のレコードのタイプを示します。レコードには、通常のレコード用に0、B +ツリーの非リーフノードレコード用に1、最小レコード用に2、最大レコード用に3の合計4つのタイプがあります。
自分で挿入するレコードは通常のレコードであり、それらのrecord_type値は0ですが、最小レコードと最大レコードのrecord_type値はそれぞれ2と3です。
- next_record
現在のレコードの実データから次のレコードの実データへのアドレスオフセットを表します。
次のレコードは、挿入順に次のレコードを参照するのではなく、主キー値の小さいものから大きいものの順に次のレコードを参照します。そして、最小レコード(最小レコード)の次のレコードは、このページで最小の主キー値を持つユーザーレコードであり、このページで最大の主キー値を持つユーザーレコードの次のレコードは最高であると規定されています。レコード(最大レコード)。
図に示すように、レコードは主キーの小さいものから大きいものの順に単一リンクリストを形成します。
ページ内のレコードをどのように追加、削除、または変更しても、InnoDBは常に単一のリンクリストを維持します。 。値は昇順で連結されます。例:2番目のレコードを削除した後の概略図:
主キー値が2のレコードは削除されましたが、ストレージスペースは再利用されませんでした。このレコードをテーブルに再度挿入しても、InnoDBは影響を受けません。新しいレコード。代わりに、元の削除されたレコードのストレージスペースを直接再利用します。(データページに複数の削除されたレコードがある場合、これらのレコードのnext_record属性は、これらの削除されたレコードのガベージリストを形成するため、ストレージスペースのこの部分は後で再利用できます。)
Q:ポインタnext_recordは、レコードヘッダー情報と実際のデータの間の位置を指すように何を要求しますか?レコードの追加情報が始まるレコード全体の先頭を指すだけではどうでしょうか。
回答:この位置はちょうど良いので、左への読み取りは記録ヘッダー情報であり、右への読み取りは実際のデータです。さらに、可変長フィールド長リストとNULL値リストの情報は逆の順序で保管されるため、レコードの先頭にあるフィールドと、メモリー内の対応するフィールド長情報との間の距離を近づけることができます。これにより、キャッシュメモリが向上する可能性があります。ヒット率。
2.ページ構造の詳細な説明
1.ページディレクトリ
レコードを照会する場合:
SELECT * FROM page_demo WHERE c1 = 3;
最も愚かな方法:最小のレコード(最小のレコード)から始めて、リンクリストを上に向かって進めていきます。リンクリスト内の各レコードの値は昇順で並べられているため、リンクリスト内のノードによって表されるレコードの主キー値が検索する主キー値よりも大きい場合は、検索を停止できます。ただし、ページに非常に多くのレコードが格納されている場合でも、このルックアップはパフォーマンスを大量に消費します。
通常、本から特定のコンテンツを検索する場合は、通常、最初に目次を確認し、検索する必要のあるコンテンツに対応する本のページ番号を見つけてから、対応するページ番号に移動して、コンテンツ。InnoDBも、レコード用に同様のディレクトリを作成します。
- すべての通常のレコード(削除済みとしてマークされたレコードを除く、最大および最小のレコードを含む)をグループに分割します。
- 各グループの最後のレコード(つまり、グループ内で最大のレコード)のヘッダー情報n_ownedこの属性は、レコードに含まれるレコードの数、つまりグループ内のレコードの数を示します。
- 各グループの最後のレコードのアドレスオフセットは個別に抽出され、ページの終わり近くに順番に保存されます。この場所は、ページディレクトリと呼ばれるいわゆるページディレクトリです。ページディレクトリ内のこれらのアドレスオフセットは、溝(スロット)なので、このページディレクトリはスロットで構成されています。
たとえば、page_demoテーブルには6つの通常のレコードがあり、InnoDBはそれらを2つのグループに分割します。最初のグループには最小レコードが1つだけあり、残りの5つのレコードは2番目のグループにあります。
minおよびmaxレコードのヘッダー情報のn_ownedプロパティ:
- 最小のレコードのn_owned値は1です。これは、グループ内で最小のレコードで終わるレコードが1つだけであることを意味します。これは、最小のレコード自体です。
- 最大のレコードのn_owned値は5です。これは、最大のレコード自体と自分で挿入した4つのレコードを含め、最大のレコードで終わるグループには5つのレコードしかないことを意味します。
アドレスオフセットは矢印を指すように置き換えられ、レコードとページディレクトリの関係は純粋に論理的に表されます。
規定:最小のレコードが配置されているグループの場合、レコードは1つのみ、最大のレコードが配置されているグループは1〜8レコード、残りのグループのレコード数は4のみです。 〜8小節の間
- 最初は、データページには2つのグループに属する最小のレコードと最大のレコードの2つのレコードしかありません。
- 各レコードが挿入された後、主キー値がこのレコードの主キー値よりも大きく、差異が最も小さいスロットがページディレクトリから検出され、スロットに対応するレコードのn_owned値が次のようにインクリメントされます。 1は、このグループが再度追加されたことを示します。グループ内のレコード数が8になるまで1レコード。
- グループ内のレコード数が8に等しく、レコードが挿入されると、グループ内のレコードは2つのグループに分割されます。1つは4レコード、もう1つは5レコードです。このプロセスにより、ページディレクトリにスロットが追加され、新しいグループの最大レコードのオフセットが記録されます。
データページで指定された主キー値を持つレコードを検索するプロセス
- 二分法によってレコードが配置されているスロットを特定し、スロット内で主キー値が最小のレコードを見つけます。
- スロットが配置されているグループ内のレコードを、レコードのnext_recordプロパティを介してトラバースします。
2.ページヘッダー
ページヘッダーこれは、ページ構造の2番目の部分です。この部分は、固定56バイトを占め、さまざまなものを格納するために使用されます。ステータス情報。
- PAGE_DIRECTION
新しく挿入されたレコードの主キー値が前のレコードの主キー値より大きい場合、このレコードの挿入方向は右であると言います。そうでない場合は左です。最後のレコードの挿入方向を示すために使用される状態は、PAGE_DIRECTIONです。 - PAGE_N_DIRECTION
は、新しいレコードを挿入する方向が数回連続して同じであると想定します。InnoDBは同じ方向に挿入されたレコードの数を記録し、この数はPAGE_N_DIRECTIONの状態で表されます。もちろん、最後のレコードの挿入方向が変更された場合、この状態の値はクリアされ、再度カウントされます。
3.ファイルヘッダー
ページヘッダーは、データページ専用に記録されたさまざまなステータス情報です。
ファイルヘッダーはさまざまなタイプのページに共通です。つまり、さまざまなタイプのページは、さまざまなページに共通するいくつかの情報を説明する最初のコンポーネントとしてファイルヘッダーを使用します。
- FIL_PAGE_SPACE_OR_CHKSUM
は、現在のページのチェックサムを表します。
チェックサムは、非常に長いバイト文字列の場合、この非常に長いバイト文字列を表すために、何らかのアルゴリズムを使用して比較的短い値を計算することです。この比較的短い値は、チェックサムと呼ばれます。このように、2つのロングバイト文字列のチェックサムは、2つのロングバイト文字列を比較する前に比較されます。チェックサムが異なる場合は、2つのロングバイト文字列が異なる必要があるため、直接比較は省略されます。長いバイト文字列。
- FIL_PAGE_OFFSETの各ページに
は個別のページ番号があり、InnoDBはページ番号を介してページを一意に見つけることができます。 - FIL_PAGE_TYPE
これは、現在のページのタイプを表します。
InnoDBは、目的ごとにページをさまざまなタイプに分割します。上記で紹介したデータページは、実際にはレコードを格納するデータページです。実際、他にも多くのタイプのページがあります。(データページのタイプは、実際にはFIL_PAGE_INDEXであり、いわゆるインデックスページです)
- FIL_PAGE_PREVとFIL_PAGE_NEXTの両方の
InnoDBは、データをページ単位で格納します。非常に大きなスペースを占める特定の種類のデータを格納する場合があります。InnoDBは、この量のデータに非常に大きなストレージスペースを一度に割り当てることができない場合があります。複数の不連続ページに格納されている場合、これらのページを関連付ける必要があります。FIL_PAGE_PREVとFIL_PAGE_NEXTは、それぞれこのページの前のページと次のページのページ番号を表します。二重リンクリストを作成することにより、ページが物理的にリンクされることなく、多くのページがリンクされます。
すべてのタイプのページに前のページ属性と次のページ属性があるわけではありませんが、データページ(FIL_PAGE_INDEX)にはこれら2つの属性があるため、すべてのデータページは実際には二重リンクリストです。
4.ファイルトレーラー
InnoDBストレージエンジンはデータをディスクに保存しますが、ディスク速度が遅すぎるため、ページ単位で処理するためにデータをメモリにロードする必要があります。ページ内のデータがメモリ内で変更された場合は、特定の変更された時間は、データをディスクに同期する必要があります。
データの同期時に何らかの要因(停電など)により同期が終了した場合はどうなりますか?そのため、ページが完全であるかどうかを検出するために、InnoDBは各ページの最後に8バイトで構成されるファイルトレーラー部分を追加します。
- 最初の4バイトは、ページのチェックサムを表します。
この部分は、ファイルヘッダーのチェックサムに対応します。ページがメモリ内で変更されるたびに、同期の前にチェックサムを計算する必要があります。ファイルヘッダーがページの前にあるため、チェックサムは最初にディスクに同期されます。完全に書き込まれると、チェックサムは次のようになります。また、ページの最後に書き込まれます。完全な同期が成功した場合、ヘッダーとページの最後のチェックサムは同じである必要があります。書き込みの途中で電源が切れた場合、ファイルヘッダーのチェックサムは変更されたページを表し、ファイルトライアルのチェックサムは元のページを表します。2つの違いは、同期が途中であるということです。問題が発生しました。 。 - 最後の4バイトは、ページの最後の変更に対応するログシーケンス位置(LSN)を表します。
この部分は、ページの整合性を検証するためにも使用されます。
メモリからディスクに同期されたページの整合性を確保するために、ページ内のデータのチェックサムとページの最後の変更に対応するLSN値が、ページの先頭と末尾に格納されます。ヘッドとテールのチェックサムとLSN値は次のとおりです。検証が失敗した場合は、同期プロセスに問題があることを意味します。
ファイルトレーラーはファイルヘッダーに似ており、すべてのタイプのページに共通です。
3.まとめ
各データページは二重にリンクされたリストを形成でき、各データページのレコードは、小さいものから大きいものへの主キー値に従って単一各データページはそれに格納されたレコードのページディレクトリを生成します。主キーを使用してレコードを検索する場合、ページディレクトリで二分法を使用して対応するスロットをすばやく見つけ、スロットの対応するグループ内のレコードをトラバースして、指定したレコードをすばやく見つけることができます。
その中で、ページa、ページb、ページc ...ページnこれらのページは、二重にリンクされたリストを介して関連付けられている限り、物理的な構造で接続されていない可能性があります。