データベースファイル形式
データベース全体は、「メインデータベースファイル」と呼ばれるディスク上の単一のファイルに保存されます。 トランザクション中、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ツリーページの構造は次のとおりです。
- データベースファイルヘッダー(100バイト)
- Bツリーページタイトル(8または12バイト)
- セルポインターの配列
- 未割り当てスペース
- セルの内容
- 予約場所
データベースファイルのヘッダーは最初のページでのみ見つかります。最初のページは常に「テーブルB-ツリー」の老人です。 データベース内のBツリーの他のすべてのページには、このヘッダーはありません。
Bツリーページヘッダーは、リーフページでは8バイト、内部ページでは12バイトです。 表2は、ページタイトルの構造を示しています。
表2
Freeblockは、Bツリーページ内の未割り当て領域を定義するために使用される構造です。 Freeblockはチェーンで構成されています。 フリーブロックの最初の2バイト(最高から最低)、これは次のフリーブロックへのオフセット、またはフリーブロックがチェーンの最後の場合はゼロです。 3番目と4番目のバイトは、4バイトのヘッダーを含むフリーブロックのサイズ(バイト単位)の整数です。 フリーブロックは常に、変位の昇順で接続されます。
断片化されたバイト数は、セルコンテンツ領域内の未使用バイトの総数です。
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を批判してくれてありがとう (もちろん移動できますが、まあまあ)。