鱒身(Masu_mi)のブログ

知った事をメモする場所。

SQLite4が現れた!

SQLite3の勉強を放置しているうちにSQLite4が出ていた。 なので今回はThe Design Of SQLite4の超訳(すっとばし)と補足を書く。

SQLite3を読んでSQLiteは標準のB-Treeを基盤に仮想テーブルを使って色々なデータ構造をSQLで糊付けする抽象化層ライブラリってイメージを持っていた。 SQLite4は各コンポーネントの責任範囲を明確にして全体を単純に扱えるようにしている印象を受けた。 例えば、 プラガブルなストレージエンジンは、データモデル(トランザクション・データ構造)をデータベース全体で統一させている。 これはテーブル単位でのデータ構造切り替え(仮想テーブル)よりも単純化されていて扱いやすそうに思えた。 また、実行環境オブジェクトは複数のDB接続をユーザー側で明示的に管理しないといけなくしている。

参考資料のリンクを残す

2.0 概要 の大枠

  1. ACIDを完全にサポートしたSQLベースの組み込みDBでI/Oはディスクに直接向かう
  2. ライセンスは今まで通りパブリックドメイン
  3. 動的型付けを使っている
  4. デフォルトは1ファイルでフォーマットは安定しておりドキュメンテーションされてる
  5. 高速で信頼性があり管理者が不要
  6. 依存が少なく組み込みや一般的でない実行環境にも移植しやすい

ここだけ見るとSQLite3との違いは少なそう。

3.0 主要な変更点 の概要

3.1 実行環境オブジェクト

いくつかのSQLite4のAPIで実行環境を定義したsqlite4_envへのポインタが第一引数に追加された。

  • sqlite4_open()
  • sqlite4_malloc(), sqlite4_realloc(), and sqlite4_free()
  • sqlite4_mprintf()
  • sqlite4_random()
  • sqlite4_config()

sqlite4_envは実行環境を表していてシステムの他の部分とのコミュニケーションを保持する。メソッドは色々あるので原文を読んで欲しい。 上記で紹介した関数でsqlite4_envNULLポインタを渡すとグローバルなデフォルトのsqlite4_envオブジェクトが使用される。 異なるsqlite4_envを使えばmutex, heapなどが共用されないため同一プロセスで複数のsqlite4の利用が可能。

3.2 単純化されたKey/Value ストレージエンジン

SQLite4はKey/Valueストレージエンジンを利用するようになった。 これはSQLite3に比べてインタフェースが単純化されており更にプラガブルになっている。 新たなDBコネクションを開始する前にsqlite4_envを変更する事で動的に変更できる。

Key/Valueをテーブルを横断してグローバルに存在して辞書順ソートされている。 ストレージエンジンは切り替えれてデフォルトのストレージエンジンはlog-structured merge データベースでありLevelDBより早い。 B-Treeストレージエンジンも今後も提供される予定。

3.3 プライマリキーが本当にプライマリキーになった

SQLite3まではプライマリキーも内部的にはユニーク制約のインデックスのため 実際にレコードにアクセスするためと検索するためとで最低2回のI/Oが発生していたけれど今回からは違う。 そしてプライマリキーはnon nullが要求される。これは普通なんだけどSQLite3では初期バージョンでは強制していなく幅広いユースケースを見るとNOT-NULL制約を有効化するとトラブルが生じるプログラムが多く存在する。

3.4 10進数

SQLite4では10進数を使う。整数型も浮動小数点型も内部に翻訳されて利用される。 内部では1から12バイトのバイト列で表現される。

IEEE754のバイナリ64浮動小数点がサポートされない環境でも動く だいたいの状況で正確で丸め誤差がない すべての符号(あり/なし)64bit整数型は正確に表現出来る 浮動小数点の範囲や正確さはIEEE754のバイナリ64浮動小数点のそれらを超える 正負の無限大とNaN(Not-a-Number)がwell-defined になる表現を取っている

3.5 外部キー制約と再帰的なトリガーがデフォルトに

SQLite3では、初期バージョンで外部キー制約は使用できなかったため、後方互換性のためデフォルトでは有効になっていませんでした。しかしSQLite4ではデフォルトで有効です。 外部キー制約はデフォルトでは遅延制約になっています。しかし定義時に即時制約(Immediate)にする事も可能になっている。ただし外部キー制約の遅延と即時を切り替える仕組みは備えていない。 SQLite4では再帰的なトリガーがデフォルトでサポートされている。

3.6 明示的なCovering Index

Coveringインデックスがサポートされている。そのためインデックスに読むだけの情報を指定する事が可能となっている。 これによりインデックスで検索後にプライマリキーを用いてレコードを読み出しという探索が2回発生する状況を、インデックスで検索時に同時に情報を読み出しという探索が1回の形に変更できる。

これはSQLite4ではアプリケーションエンジニアに容量と時間の対立を明確に選択できるようにしている事を表している。