SQLiteファイル構造

この投稿では、SQLiteデータベースがコンテキストで考慮されます。データベースファイルの構造に関する情報、メモリ内のデータの表現に関する情報、およびBツリーの構造とファイル表現に関する情報を見つけることができます。



データベースファイル形式



データベース全体は、「メインデータベースファイル」と呼ばれるディスク上の単一のファイルに保存されます。 トランザクション中、SQLiteは追加情報を2番目のファイルに保存します。ロールバックジャーナル、またはデータベースがWALモードの場合、レコードに関する情報を含むログファイルです。 トランザクションの終了前にアプリケーションまたはコンピューターがシャットダウンした場合、これらのファイルは「ホットジャーナル」または「ホットWALファイル」と呼ばれ、データベースを一貫した状態に復元するために必要な情報が含まれます。



Pages



メインデータベースファイルは、1つまたは複数のページで構成されます。 1つのデータベース内のすべてのページのサイズは同じで、512〜65536バイトです。 データベースファイルのページサイズは、データベースファイルの先頭から16バイトのオフセットを持つ2バイトの整数で決まります。

すべてのページには1〜2147483646(2 ^ 31-2)の番号が付けられています。 最小データベースサイズ: 512バイトの 1ページ、最大データベースサイズ:65536バイトの2147483646ページ(〜140 TB )。



見出し



データベースファイルの最初の100バイトにはデータベースヘッダーが含まれています。表1にヘッダースキームを示します。



表1






ロックバイトページ



ロックページはデータベースファイルの1ページであり、オフセット0x1073741824と0x1073742335の間にあります。データベースのサイズが小さい場合、ロックページはありません。 このページは、OSインターフェイスのロックプリミティブを実装するために必要です。



フリーリスト



空白ページのリストは、リンクリストとして整理されています。 各リスト項目は、4バイトの2つの数字で構成されています。 最初の番号は、次の空きリスト(トランクポインタ)要素の番号を決定します。リストが終了している場合はゼロです。 2番目の番号は、リーフページ番号へのポインターです。 次の図は、この構造の図を示しています。







B-ツリー



SQLiteは、2つのタイプのツリーを使用します。「テーブルB-ツリー」(データは葉に保存されます)および「インデックスB-ツリー」(キーは葉に保存されます)。

「テーブルB-ツリー」の各エントリは、64ビット整数キーと最大2147483647バイトの任意のデータで構成されます。 キー「テーブルB-ツリー」は、SQLテーブルのROWIDに対応します。

「インデックスB-ツリー」の各エントリは、最大2147483647バイトの任意のキーで構成されます。



ページB-ツリー



Bツリーページの構造は次のとおりです。





データベースファイルのヘッダーは最初のページでのみ見つかります。最初のページは常に「テーブルB-ツリー」の老人です。 データベース内のBツリーの他のすべてのページには、このヘッダーはありません。



Bツリーページヘッダーは、リーフページでは8バイト、内部ページでは12バイトです。 表2は、ページタイトルの構造を示しています。

表2




Freeblockは、Bツリーページ内の未割り当て領域を定義するために使用される構造です。 Freeblockはチェーンで構成されています。 フリーブロックの最初の2バイト(最高から最低)、これは次のフリーブロックへのオフセット、またはフリーブロックがチェーンの最後の場合はゼロです。 3番目と4番目のバイトは、4バイトのヘッダーを含むフリーブロックのサイズ(バイト単位)の整数です。 フリーブロックは常に、変位の昇順で接続されます。



断片化されたバイト数は、セルコンテンツ領域内の未使用バイトの総数です。


セルポインターの配列は、セルの内容の2バイト整数K個のオフセットで構成されます(BツリーにK個のセルがあります)。 配列は(最小のキーから最大のキーへ)昇順でソートされます。



未割り当て領域とは、ポインタ配列の最後のセルと最初のセルの先頭の間の領域です。



各ページの最後にある予約済みスペースは、ページに関する情報を保存するために拡張機能によって使用されます。 予約領域のサイズは、データベースのヘッダーで決定されます(デフォルトはゼロ)。



代表者



このセクションでは、データベース内のデータストレージの構造について説明します。 テーブルbツリーおよびインデックスbツリーキーのシートページのデータは、 レコード形式と呼ばれる任意のバイトシーケンスとして格納されます (詳細はhabrahabr.ru/post/223451 )。



テーブル



各テーブル(ROWIDを使用)は、データベースではテーブルbツリーとして表されます。 ツリーの各エントリは、SQLテーブルの行に対応しています。 SQLテーブルの1行は、レコード形式のテーブル列のシーケンス(作成時に指定されたものと同じ)として表されます。 テーブルにROWIDのエイリアスであるINTEGER PRIMARY KEYがある場合、値の代わりにNULLが書き込まれます。 SQLiteは、INTEGER PRIMARY KEYにアクセスするときに、常にNULLではなくキーテーブルb-ツリーを使用します。 Affinity列(タイプ変換の推奨、「データタイプと値の比較」セクションの詳細habrahabr.ru/post/149635 )がREALであり、値をデータ損失なしでINTEGERに変換できる場合、値は整数として保存されます。 データベースからデータを取得するとき、SQLiteは整数をREALに変換します。



ROWIDなし



各テーブル(ROWIDなし)は、データベースではインデックスbツリーとして表されます。 ROWIDを持つテーブルとの違いは、各SQLテーブルレコードのキーがレコード形式で格納され、キー列がPRIMARY KEYで指定されたとおりに格納され、残りがテーブル宣言で指定された順序で格納されることです。

したがって、 インデックスのbツリーのエントリは、列の順序と行の内容がツリーキーに格納されているという事実を除き、 テーブルbツリーのように表示されます



INDEX



各インデックス(CREATE INDEX、PRIMARY KEYまたはUNIQUEとして宣言)は、 インデックスb-ツリーの形式でデータベースに表されます。 このようなツリーの各レコードは、SQLテーブルの行に対応しています。 インデックスツリーキーは、インデックスで指定された列値のシーケンスであり、レコード形式の行キー(rowidまたは主キー)の値で終わります。



UPD 13:44代表セクションが再設計されました。mayorovpを批判してくれてありがとう (もちろん移動できますが、まあまあ)。



All Articles