はじめに
SQLite は世界で一番使われている だから世界で一番凄いものに決まってるだろ
SQLite は世界で最も使われている RDBMS です。名前に反して(?)おもちゃの RDBMS ではありません。元ネタと同じで 一番普及しているからと言って必ずしも一番凄いものであるとは限りませんが、普及しているのであればそこには何かしらの理由があるはずです。その理由を調べないことには、凄いか凄くないかの結論は出せないので SQLite のなにがそんなに凄いのかを調査しました。
2022/04/01 続編記事↓を書きました。
注意 この記事は「なぜシェルスクリプトで高度なデータ管理にSQLiteを使うべきなのか? ~ UNIX/POSIXコマンドの欠点をSQLで解決する」の補足記事して書いたものです。ところどころ不自然にシェルスクリプトや Unix コマンドの話が登場するのはそのためです。基本的に SQLite の公式サイトの情報を元に書いており実際に使用した検証は(まだ)行っていません(正確に言えば 10年以上前に Perl で使ったことはあるのですが、忘れていますしさすがに再検証が必要でしょう)。SQLite の代替として使える DBMS には Realm などがあるようですが、個人的にシェルスクリプトからでも容易に使える事という前提があるため詳しく調べていません。また SQLite 単体を調べたものであり他の DBMS との比較ではありません。
(おまけ記事 あなたは世界初の「NoSQL」はシェルスクリプト用のRDBMSだと知っていますか?)
SQLite とはどのような特徴を持つ RDBMS なのか?
なぜ SQLite の利用者は数十億人もいるのか?
ネタバレしてしまえば、Android や iOS、つまりスマホに組み込まれているからです。スマホは世界で 40 億人(2021年6月時点)が所有しているため、SQLite も同等数以上の人が(間接的に)使っているということになります。
クライアント・サーバー型ではなく組み込み型のライブラリ
SQLite は RDBMS ですが、他の多くの RDBMS とは違いクライアント・サーバー型ではなく組み込み型のライブラリです。TCP や Unix ソケットなどを使用してデータベースサーバーに接続するタイプではなく SQLite ライブラリが組み込まれたアプリケーションから、直接データベースファイルを読み書きするという仕組みです。ライブラリ自体は C 言語で実装されていますが、その他の言語でも C 言語バインディング経由で対応しており、ほぼすべての言語からデータベースファイルを読み書きすることができます。(SQLite に対応できない言語としてシェルスクリプトがありますが、標準で sqlite3
コマンドが提供されているので、シェルスクリプトからでもコマンド経由で間接的に読み書きすることができます。)
念の為に補足しておくと SQLite はファイルアクセスのライブラリに過ぎないため、ウェブシステムでデータベースサーバーとフロントエンドを分けるような、よくあるシステム構成や、ネットワークで多数のコンピュータを連携させる大規模システムに対応することはできません(一台のコンピュータで十分なほど、アクセス数が少なくて負荷が軽い小規模のウェブサーバー程度であれば対応可能です)。SQLite はそのような大規模なシステムと対応できるものとして作られていませんが、それ故に組み込み型としてはシンプルに使うことができる優れたライブラリとなっています。
CLI インターフェースが付属している
SQLite は組み込み型のライブラリですが、CLI インターフェース(sqlite3
コマンド)も公式に付属しています。そのため一般的な Unix コマンド(例 awk
コマンド等)の代わりとして SQLite を使うことができます。SQLite には豊富なデータ処理の機能が含まれておりテキスト処理を行う Unix コマンドを使う必要はほとんど無くなるため、Unix コマンドで大きな問題となっている環境間で機能や互換性の低さを大幅に改善することが出来ます。
他のデータベースソフトでも CLI インターフェースが付属していることは多いですが、それらはデータベースサーバーとネットワークで通信するフロントエンドです。一方 sqlite3
コマンドは SQLite ライブラリを組み込んだコマンドラインユーティリティです。一般的に重い処理とされるサーバーとのコネクション確立処理が不要でコマンド単体で SQLite データベースファイルを読み書きするため、クライアント・サーバー型の CLI コマンドよりもレスポンスが良くシェルスクリプトとの相性も良いです。
念の為に補足しておくと、シェルスクリプトから SQLite を利用する場合は sqlite3
コマンド経由での間接的な読み書きとなるため、ネイティブにファイルを読み書きする他の言語よりはパフォーマンスは劣ります(SQLite だけではなく Unix コマンド全般に当てはまる話です)。ただし SQLite はデータ管理専用に作られたものなので他の汎用のテキスト処理を行う Unix コマンドを使って自前でデータ管理を行うよりはパフォーマンスは高く簡単に高度なデータ管理を行うことが出来ます。
SQLite が適している用途(IoT・小規模ウェブサイト等)
- 組み込み機器や IoT
- データベース管理を必要としないので専門家のサポートなしで動作する
- アプリケーションファイルフォーマット
- さまざまアプリケーションのファイルの代わりに使用できる
- ウェブサイト
- SQLite のウェブサイトは SQLite を使用しており 1 日 40 万~50万 の HTTP リクエストを処理
- データ分析
- どの言語でも扱えるデータベース形式なので R や Python など言語をまたがったデータ分析を行うことができる
- エンタープライズデータのキャッシュ
- ローカルでの一時的なキャッシュ
- サーバーサイドのデータベース
- サーバーサイドのソフトウェアで使用するデータの実際の保存先
- データ転送形式
- クロスプラットフォームで移植性が高いデータ形式
- ファイルアーカイブ・データコンテナ
- ZIP アーカイブや tar の代わりとしてファイルを圧縮して格納することができる
- アドホックディスクファイルの置き換え
- 多くのプログラミング言語のファイル読み書きの代わり(ファイルシステムより高速)
- 内部または一時データベース
- インメモリで処理できるため、一部のアルゴリズム(ソートなど)の代わりとして使える
- デモやテスト中に使用するエンタープライズデータベースの代用
- 最終的には別の DBMS を使うにしろ、デモやテスト中にその代替として使える
- 教育と訓練
- セットアップが簡単なので SQL の学習に最適
- 実験的な SQL 言語拡張
- SQL の言語を拡張するなどの実験
SQLite が適さない用途(大規模ウェブサイト・ビッグデータ等)
- クライアント/サーバーアプリケーション
- プログラムとデータベースがネットワークで分離されている場合
- 大量のアクセスがあるウェブサイト
- 書き込みが多い・複数のサーバーが必要な場合など
- 非常に大きなデータセット
- ビッグデータ、SQLite のデータベースファイル 281 TB までしか対応してない
- 高い並列性
- 多数のユーザーが同時に書き込みを行う場合など
面白いことに SQLite が適さない用途はシェルスクリプトが適さない用途と一致しています。これらの用途ではシェルスクリプトは使えませんが、逆に言えばシェルスクリプトが使える(かつ高度なデータ管理をするならば)SQLite を使った方が良いというのとほぼ同義です。
SQLite が安心して使えるデータベース管理システムである理由
20 年以上問題なく利用された実績があり高い信頼性が証明済み
SQLite は世界中の数十億のスマートフォン、IoT デバイス、デスクトップアプリケーションで、20 年以上問題なく使用されおり、高い信頼性が十分以上に証明されています。
POSIX/ANSI C に完全に準拠しておりどこでも動く
SQLite が C 言語で作られている理由は互換性、低依存性、安定のためです。SQLite は POSIX / ANSI C で標準化されている OS のインターフェース(関数)しか使っておらず POSIX に完全に準拠したソフトウェアです。それだけじゃないと言わんばかりに、SQLite (最小構成)で使っている関数までしっかりドキュメント化されています。
SQL が使用している POSIX API (および ANSI C の関数) は、以下のわずか 7 個の基本的な関数だけです
-
memcmp()
,memcpy()
,memmove()
,memset()
,strcmp()
,strlen()
,strncmp()
完全なビルドだともう少し追加の関数が必要なようですが、それでも基本的なものしか使われていないとのことです。たったこれだけの関数で RDBMS なんて作れるものなの?と思うかもしれませんが、よくよく考えてみるとデータベースなんて計算処理とファイルの読み書きしかしないわけでこれだけで十分なわけですね。SQLite はネットワークにも対応していませんし。あとはビルドオプションからスレッド関連の API も使用しているはずです。パフォーマンスを上げるためにマルチコアを使用するためだと思いますが詳細までは調べていません。
航空グレード (DO-178B) の高い品質管理
DO-178B(航空機搭載システムおよび機器認証におけるソフトウェアの考慮事項)は特定の航空機搭載システムで使用される、セーフティクリティカルなソフトウェアの安全性を扱うガイドラインです。SQLite はこの DO-178B に基づいた品質管理(ソフトウェアの開発計画、開発環境、検証計画、構成管理等)を行っています。
注意 ただし DO-178B の認定(?)を受けていたりはしないようです。実際の DO-178B を満たすにはさまざまな、役所仕事に特有の無駄な ドキュメントが必要なため、ソフトウェア品質の向上に直接効果があると考えられるドキュメントのみを作成しているようです。
ちなみに SQLite はバージョン管理に、独自で開発した Fossil を使用しているようです。Fossil は内部で SQLite データベースを使用しています。(参考 Why SQLite Does Not Use Git)
SQLite のテストコードは 9191 万行(!)
SQLite 3.33.00 (2020) の時点で、ソースコードの行数 14 万行 (143.4 KSLOC of C code) に対して、テストコードは 9191 万 (test scripts - 91911.0 KSLOC) もあるとのこと。ソースコード 14 万行は大きいですが C 言語なのでわからないレベルではないのですが、テストコードの行数はさすがに信じられない行数ですね。言語が違うので直接比べることは出来ませんが私はテストコードの行数はソースコードと同等~数倍程度です。
2010 年の SQLite のテストコードの日本語記事「SQLiteのテストコードは4567万8000行! 本体のコードは6万7000行」と比較すると、およそ 10 年で本体のコードもテストコードも倍増していることがわかります。
どのようなテストを行っているのか、その詳細はリンク先に詳しく語られています。気が遠くなるようなテスト数ですが、基盤となるデータベース管理システムでは、ここまでしないとダメなんだということです。普通のソフトウェアでこのようなレベルでテストするなど到底不可能でしょう。
もちろん一般のアプリケーションでこのレベルのテストを費用対効果が高くないのでするべきではありません。と SQLite はそのようなことも述べています。それでも SQLite のようなインフラレベルのライブラリではやる価値があるとも語っています。そのような信頼性がある SQLite があるのですから利用しない理由はありません。これを超えるテストを行っていると証明できるのなら話は別ですが。
Maintaining 100% MC/DC is laborious and time-consuming. The level of effort needed to maintain full-coverage testing is probably not cost effective for a typical application. However, we think that full-coverage testing is justified for a very widely deployed infrastructure library like SQLite, and especially for a database library which by its very nature "remembers" past mistakes.
オープンソース(パブリックドメイン)であり誰にも独占されていない
別の人が開発したソフトウェアに依存する場合、それが将来使えなくなる可能性を考慮しなければいけないでしょう。もしそれが特定の会社が権利を持っている独自開発のプロプライエタリなソフトウェアあれば、その会社が倒産したりして使えなくなる可能性もありますし、その会社とのライセンス契約を解除するだけで使えなくなったり、一方的なライセンス料引き上げをされたりする可能性だったあります。
それに対して SQLite はオープンソースかつパブリックドメイン(権利を完全に捨てている状態)であり、完全に誰にも独占されておらず、誰でもそのソースコードを元に自分たち専用のソフトウェアを作ることが可能です。新しい機能が欲しいと思った場合、元の開発者にお伺いを立てることなく自分たちで機能を追加することも出来ます。もちろん使ったり修正したりするのにライセンス料もライセンス契約も不要です。
オープンソースでも危険なコードの混入はない
オープンソースだからといって安全とは限りませんが、それを言ったらクローズドはもっと危険です。開発者が乱心して不正なコードが埋め込んでもクローズドソースだとそれがわかりません。
オープンソースが誕生して随分と経ちオープンソースを使うことへの抵抗感はそうとう薄れていると思います。米国防総省でさえ、自前で作ろうとせずプロプライエタリよりもオープンソースを採用することを優先するようになりました。(参考 米国防総省、オープンソースをプロプライエタリより優先的に採用する調達方針を明らかに。同省CIOが書面で通知)
この説明の最初にある「採用、購入、開発」のアプローチとは、まず既存のソリューションやオープンソースでそのまま使えるものがあればそれを「採用」する、それが見つからなければプロプライエタリな商用製品を「購入」することで実現できないかを検討し、どうしても既存の製品で実現できないものだけを「開発」するという、検討すべき内容の順番を示したものです。
それでも気になる人は気になるでしょう。どこぞのアホ研究者が自分の利益(研究)のために、意図的に脆弱性のあるコードを Linux カーネルに埋め込もうと試みる事件があったりするぐらいですから。
さて、では SQLite はどうなのかというと、その心配はありません。なぜならオープンソースであってもオープンコントリビュートではない、つまり他の人からコードの提供を受け付けてないからです。SQLite のソースコードを元に自分達だけで使うための修正を独自に加えるのは可能です。しかしそれが本家にマージされることはありません。何かしらのコードが提供されたとしても、開発者自身が(再)実装すると公表しています。
Open-Source, not Open-Contribution
But SQLite is not open-contribution. In order to keep SQLite in the public domain and ensure that the code does not become contaminated with proprietary or licensed content, the project does not accept patches from people who have not submitted an affidavit dedicating their contribution into the public domain.Contributed Code
In order to keep SQLite completely free and unencumbered by copyright, the project does not accept patches. If you would like to suggest a change and you include a patch as a proof-of-concept, that would be great. However, please do not be offended if we rewrite your patch from scratch.
オープンソースとしては変わった方針に思えるかもしれませんが、SQLite レベルのインフラソフトウェアでは理にかなった方針です。これにより悪意のあるコードが含まれないだけではなく SQLite に誰かが権利を主張するコードが紛れ込むことなく、永久にパブリックドメインのままで高い信頼性と安全性が担保されます。
サポートや保証が必要なら Hipp, Wyrick & Company, Inc 社から購入可能
★ Professional Support & Extension Products
★ License And Warranty Of Title
Hipp, Wyrick & Company, Inc., (Hwaci)は SQLite の開発者が SQLite のサポートのために設立した会社です。
SQLite は無料で使えますがサポートもありません(無料で利用できる公式のパブリックフォーラムならあります)。もし特別なサポートが欲しい時や権利問題が発生したときの「保証があるものしか使ってはならないと会社に言われている」ような場合は、お金を出して買うことも出来ます。安心感が欲しい会社はそれを買うのもいいでしょう。
データベースファイル形式もきっちりドキュメント化されている
ソースコードはパブリックドメインですが、コードを読んで理解しろっていうのも大変な話です。ライブラリの形でソースコードが公開されており SQLite のデータベース形式を扱える独自のソフトウェアはいくらでも作ることが可能ですが、SQLite のライブラリを使わずに自力でファイルを読み書きしたいのであれば、データベースファイル形式もしっかりとドキュメント化されているので、それを読むと良いでしょう。
SQLite のデータベース形式はバイナリファイルですが、バイナリファイルだからって、中身が読むのが大変なわけではありません。例えば圧縮ファイル(バイナリ)の中身だって zcat
を使えば中身は読めますよね?対応したツールを使えば見れるので別にテキストファイル形式じゃないと中身が見れないということはありません。重要なことはファイルフォーマットがきちんとドキュメント化されていることです。
反対にテキストファイルベースであっても独自の決まりがある場合は正しく扱うのは大変です。例えば SVG ファイル(画像フォーマットの一種)は XML ベースでテキストファイルですが、それをテキストエディタで文字が読めたからと言って画像としての意味がわかるわけではありませんし編集できるわけでもありません。SVG ファイルを扱える専用の表示・編集ソフトが必要です。結局の所、ファイルを読み書きできるかというのはテキストかバイナリかではなく、それがきちんと仕様化されていて簡単に読み書きできるライブラリやツールが有るかどうかです。
SQLite はデータベースファイル形式の仕様がきっちりとドキュメント化されており、簡単に読み書きするツールもあります。
ファイル形式は長期保存に推奨できるとの米国議会図書館のお墨付き
★ LoC Recommended Storage Format
いくらデータベースファイルの形式がドキュメント化されているように見えても、記述漏れや曖昧なところがあるかもしれません。ドキュメントがあるだけじゃ信用できないよというような方には「あの米国議会図書館までもが長期保存に推奨できると認めてる!」という宣伝文句が有効でしょう。第三者の手によって認められているため、本人が主張するだけよりも説得力が高まります。
米国議会図書館の推奨するストレージ形式は、以下の内容を考慮して決められているそうです。(詳細)
- Disclosure(開示) 完全な仕様とツールが存在すること
- Adoption(採用) 多くの採用実績があること
- Transparency(透明性) テキストエディタや基本的なツールで読み取れること
- Self-documentation(自己文書化) データ自体に基本的な記述や管理用メタデータなどが含まれていること
- External Dependencies(外部依存性) 特定の OS やハードウェアやソフトウェアに依存しないこと
- Impact of Patents(特許の影響) 特許問題が発生しないこと
- Technical Protection Mechanisms(技術的保護メカニズム) 暗号化技術などに対応できること
2018-05-29 時点で SQLite 以外のフォーマットは XML、JSON、CSV しか認められていないと書かれていますが、今は随分と増えている気がします。たぶんこれです ⇒ Sustainability of Digital Formats: Planning for Library of Congress Collections(デジタル形式の持続可能性: 米国議会図書館コレクションの計画)
Google も Apple も Microsoft も SQLite を使っている
権威に弱い人であれば「Google や Apple や Microsoft といった大手ソフトウェア会社も SQLite を使っています」という言葉が有効でしょう。以下の会社(もちろんごく一部に過ぎません)が SQLite を使用してます。
Adobe AIRBUS Apple Bentley BOSCH Dropbox Expensify
facebook Flame Google Intuit McAfee McAfee General Electric
Mozilla PHP Python RedHat skype Tcl/Tk xojo
★ Most Widely Deployed and Used Database Engine
- すべての Android デバイス
- すべての iPhone と iOS デバイス
- すべての Mac
- すべての Windows10 マシン
- すべての Firefox、Chrome、Safari
- すべての Skype
- すべての iTunes
- すべての Dropbox クライアント
- すべての TurboTax と QuickBooks
- PHP と Python
- ほとんどのテレビセットとセットトップケーブルボックス
- ほとんどの自動車マルチメディアシステム
- 数え切れないほど多くのその他のアプリケーション
Google も Apple も Microsoft も大手ソフトウェア会社です。大手ソフトウェア会社ですからデータベース管理システムを自分たちで作ることもできたでしょう。実際に Microsoft はサーバー用の MS SQL Server と クライアント用の MS Access という二種類のデータベース管理システムを開発しています。それなのに Windows 10 に SQLite を採用しています。ここは重要なポイントだと思います。OS を作っている会社から見ても SQLite は必要なソフトウェアであり、SQLite レベルのものを作るのは大変であり、自分たちで作るよりも採用した方が良いと考えたということです。
互換性が高く SQLite をアップデートしてもソフトウェアの修正は不要
SQLite は高い互換性を維持しています。SQL にも互換性がありますしファイル形式にも互換性があります。「互換性がない方法で変更しない」と明確にしています。
The underlying file format for SQLite databases does not change in incompatible ways.
SQLite データベースファイルはすでに、何千億~何兆も流通しているため互換性を保たないという選択肢はありえません。
一応書いておくと、2004 年に登場した SQLite 3.0 のデータベースファイル形式は、古いバージョンの SQLite では読み取れなくなりましたが、重要なのは新しいバージョンの SQLite で読み取れることです。新しいバージョンの SQLite で古いデータベースファイルが形式が読み取れなくなったことはありません。
2050 年までの長期サポートが目標
SQLite は 2050 年までサポートを行うと公表されています。この記事を書いた時点で 1.0 のリリースからおよそ 22 年経過しており、あと 28 年のサポートがあります。全体で 50 年 動き続けるソフトウェアです。おそらくこの目標はメインの開発者である D. Richard Hipp の年齢(28 年後は 89 歳)によって定められたものだと思います。しかし詳細なドキュメントが残されており、新しいプログラマが後を引き継げるようにとソースコードの 35% がコメント(変数とオブジェクトの意味、およびメソッドとプロシージャの意図を説明する有用なコメント)であるなど、後のプログラマのために気を配ってソフトウェアが開発されているため SQLite はもっと長く使われ続けられる可能性もあると思います。
SQLite は物理的に離れた複数のサーバーにソースコードが自動的に複製されており、SQLite の開発者も世界の様々な地域に住んでおり災害対策も考えられています。
Disaster planning → Every byte of source-code history for SQLite is cryptographically protected and is automatically replicated to multiple geographically separated servers, in datacenters owned by different companies. Thousands of additional clones exist on private servers around the world. The primary developers of SQLite live in different regions of the world. SQLite can survive a continental catastrophe.
有償の暗号化データベースファイル対応でセキュリティも高い
SQLite をファイルの代わりとするなら不要だと思いますが、エンタープライズ分野でファイルの暗号化が必要な場合、追加の拡張機能が提供されています。
SQLite が凄いデータベース管理システムである理由
データベース管理システムを使うための設定作業は全く不要である
★ SQLite Is A Zero-Configuration Database
データベース管理システムを使うのに意外と面倒なのが設定作業です。作っているのが簡単なツールで、少しデータベースが持ってるような便利な機能が使いたいだけなんだよなーというだけで、データベースサーバーをインストールして、サーバーのメンテナンスをしつつ、ツールから僅かなデータベースの機能を使うのでは割に合いません。
SQLit は多くのクライアント・サーバー型の RDBMS とは異なり面倒な設定作業を全くすることなく使うことが出来ます。データベース管理システムを使う上でありがちな面倒なメンテナンス作業も全く必要ありません。
パッケージ管理システムでインストールするだけで使える
SQLite を使うのに必要なのはパッケージ管理システムでインストールするだけの簡単な作業です。macOS など OS によってはデフォルトでインストールされている場合すらあります。もしパッケージ管理システムが使えない場合や、バージョンが古い場合などは、上記のリンクからプリコンパイル済みのバイナリファイルをダウンロードしてコピーするだけです(バイナリが用意されている場合)。プログラムがシェルスクリプト製であっても、どっちみちそれを実行する環境にシェルスクリプトをコピーしなければいけないのですからプリコンパイル済みのバイナリファイルをコピーするのも同じことですよね。
補足 Linux 版は現在 32 bit 版しかプリコンパイル済みのバイナリが配布されていないようです。そのため 64 bit 版 Linux で実行する場合は以下の方法で 32bit バイナリを実行できるように設定する必要があるかもしれません。WSL2 上の Ubuntu では必要でした。おそらく WSL1 では 32bit バイナリを実行できません。しかしソースコードからビルドするのも簡単なので、次の項目を参考に 64bit 版をビルドした方が良いでしょう。
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libc6:i386
ソースコードからのビルドも簡単である
SQLite のビルドは Hello World 並の簡単さです。ありふれたビルド環境が揃っていれば最小機能の場合これだけでビルド(コンパイル)することができます。
gcc shell.c sqlite3.c -lpthread -ldl -lm -o sqlite3
面白いのは推奨のビルド方法で、単一の sqlite3.c
(CLI インターフェースが必要な場合は追加で shell.c
)をコンパイルするだけです。configure
や make
でさえも不要です。そもそも「amalgamation」(合併)ソースコードファイルには configure
も Makefile
も付属していません。
amalgamation というのは SQLite を C 言語ライブラリとしてソフトウェアに組み込みやすくするために、オリジナルのソースコードファイルを一つのファイルにまとめたものです(オリジナルのソースコードはメンテナンスしやすいようにちゃんと複数のファイルで構成されており、一般的な configure
と make
でビルドすることができます)。一つにまとめることでコンパイラの最適化でパフォーマンスが上がるなどの理由により amalgamation を使ってビルドすることが推奨されています。
フル機能をビルドする場合でも難しい所が全くありません。参考までに Docker を使って基本的な環境からのビルドした手順を紹介します。(ビルド手順についての詳細は上記のリンク先より)
# docker run -it debian
apt-get update && apt-get -y install wget unzip gcc libreadline-dev
wget https://www.sqlite.org/2022/sqlite-amalgamation-3380000.zip
unzip sqlite-amalgamation-3380000.zip
cd sqlite-amalgamation-3380000
gcc -Os -I. -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \
-DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DHAVE_USLEEP -DHAVE_READLINE \
shell.c sqlite3.c -ldl -lm -lreadline -lncurses -o sqlite3
ここまでビルドが簡単であれば「インストールが難しいのでは?」を理由に導入を諦める必要はないでしょう?
ほとんどフル機能の SQL 実装
クライアント・サーバー方式ではないという所から SQLite は簡易な RDBMS かと思うかもしれませんがフル機能の SQL に対応しており、可読性が高いシンプルな文法を使ってデータを読み書きすることが出来ます。
私が気になったところをいくつかピックアップすると
- 無制限のテーブル、インデックス、トリガー、ビュー
- CHECK、UNIQUE、NOT NULL、外部キーなどの制約
- 部分インデックスや式インデックスなどさまざまなインデックス
- 相関サブクエリを含むサブクエリと最大 64 の join
- ACID トランザクションと排他制御
- JSON 形式対応とJSON 用関数により半構造化データを扱うことができる
- 標準 SQL の関数
- 日時関数
- 集計関数
- ウインドウ関数
- 数学関数、
数多くの便利な機能が機能がすでに提供済みであり、これらの機能をすぐに使うことがでます。SQLite にデータを格納するようにすれば、おそらく他のデータ管理の仕組みを独自で実装する必要はなくなるでしょう。
いくつか省略された機能もありますが、ごくわずかでおそらくこれらはなくても十分だと思います。
OS の API をネイティブで呼び出せる C 言語で作られているから高速
SQLite が C 言語で作られている理由の一つはパフォーマンスです。Unix/Linux 系の OS は C 言語で開発されており、OS の API は C 言語のインターフェースで呼び出すように作られています。SQLite も OS と同じ C 言語で作られており、OS に最も近い所で動作する DBMS (の一つ)であるためシステムコール呼び出しのオーバーヘッドが最も少なく最も高速に動作します。
逆にシェルスクリプトや Unix コマンドはユーザーから直接利用するものであり、OS からみれば最も遠い所で動作するソフトウェアであるためオーバーヘッドが大きくなります。多数の Unix コマンド呼び出しはシェルスクリプトを遅くする原因の一つです。シェルスクリプトから SQLite を使う場合も sqlite3
コマンド経由となりコマンド呼び出しのオーバーヘッドが加わりますが、多数の Unix コマンドを組み合わせてデータ管理を行うのとは異なり、一つのコマンド呼び出しで複雑なデータ管理を行うことが可能なため、Unix コマンドをなるべく使わないようにして、sqlite3
コマンドだけにデータ管理を任せることで実行速度を改善することができるでしょう。
ファイルシステムの直接アクセスよりも 35% も速い
★ 35% Faster Than The Filesystem
直感に反して(?)SQLite はファイルシステムへの直接アクセスより 35% 速い(日本語記事)ためファイルシステムを直接使う理由は大きく減るでしょう。これは大量のファイルがあった場合に、それらを一つづつオープン・クローズする必要がないことや、ファイルシステムのクラスタ化サイズなどが影響しているようです。
ファイルシステムへのアクセスは OS の API(システムコール)だから速いと勘違いされがちですが、実際には特権モードと非特権モードを行き来する必要があるためシステムコールを呼び出すのは遅いです。そのため可能な限りシステムコールの呼び出し回数を減らす方がパフォーマンスは上がります。データがファイルごとにわかれている場合、どうしても複数回のシステムコールを呼ばなくてはいけませんが、SQLite ではファイルが一つであるためより効率的にデータの読み書きが可能となります。
NoSQL としても使える(JSON 形式・半構造化データへの対応)
★ JSON Functions And Operators
SQLite が JSON に対応したのは 2015 年のようです。ANSI/ISO で標準化されている「標準 SQL」でも SQL:2016 で JSON 形式に対応しているので、SQLite が対応していても不思議ではありませんが、比較的新しい機能であり SQLite にも実装されていると気が付きにくいかもしれないので個別に紹介します。ちなみに他のデータベースサーバーもだいたい JSON 形式に対応しているようです。(ただし文法に関しては少々異なるようです)
Twitter など最近の多くのウェブサービスはデータ形式として JSON データを返します。そのためこのデータをそのままデータベース管理システムに入れることができるというのは大きなメリットがあります。もちろん JSON データの特定のキーをインデックスとして使ったりすることができるので、JSON データでもインデックスを使った高速な検索が可能になります。特定のキーの値で抽出したり JSON データの加工もできます。
余談ですが SQLite と近い思想で作られた NoSQL データベース管理システムとして UnQLite というプロジェクトがあります。SQLite といろいろと似ており SQLite のいくつかのソースコードを共有しているようですが、フォークではなくライセンス(UnQLite は BSD)も違います。ACID トランザクションをサポートしており、完全な NoSQL が必要な場合こちらのほうがいいかもしれませんが、おそらく実績などを考えると SQLite を NoSQL として使ったほうがいいという結論になりそうな気がします。
CSV ファイルの読み込みができる
本体に組み込まれておらず別にコンパイルしてロードする必要がありますが CSV (RFC 4180) ファイルの読み込みにも対応しています。(書き込みには対応していません)
これは SQLite の Virtual Table という機能を使って実装されています。
全文検索エンジンによる高速なテキスト検索
SQLite は高速なテキスト検索を行うための全文検索に対応しています。
という話をすると気になるのが日本語に対応しているのか?という話なのですが、やはりトークンナイザーを作らなければいけない気がします。英語は単語がスペースで区切られているので、単語の区切りが簡単にわかりますが、日本語などはそうではないので、単語を認識するための形態素解析機が必要になります。N-gram も直接対応はしてなさそうなので日本語の全文検索は少し苦労しそうです。データ投入前に MeCab などを使って分かち書き等の前処理をすればいいのですが、そうするとデータサイズは倍増してしまうんですよね。もちろん LIKE 検索などによる検索であれば普通に出来ます。
ACID 特性を備えたトランザクション対応
SQL なのでトランザクションは BEGIN
によって開始され COMMIT
(または ROLLBACK
) によって完了というように簡単な命令を実行するだけです。Savepoints を使ったネスト可能な柔軟なトランザクション制御にも対応しています。
トランザクション処理はデータベースにとって極めて重要なものであるため、簡単な命令で簡単に使えることは重要なことです。簡単な SQL を実行するだけで コミットやロールバックできることは(自分でファイルなどを使って同等のものを実装するよりも)開発コストを大幅に減らし高い信頼性をもたらすことができるでしょう。
ACID 特性とはトランザクション処理に求められる以下の言葉の略です。たまにごっちゃにしている人がいますが、排他制御はトランザクションのことではありません。排他制御はトランザクション処理を実現するための技術の一つでしかなく、排他制御があるだけではトランザクション処理ができてることにはなりません。
- Atomic(原子性)
- Consistent(一貫性)
- Isolated(独立性)
- Durable(耐久性)
Atomic(原子性)とはトランザクションに含まれる処理が「すべて実行される」か「一つも実行されない」のどちらかの状態になるという性質のことです。例えばトランザクションの処理の途中で不意に電源が遮断されたり OS の不具合で停止したとしても、データが壊れたりゴミデータが残ったりしないことです。
Consistent(一貫性)とは(例えば複数のテーブルに書き込むような)トランザクションの前後でデータが矛盾しないように整合性が保たれる性質のことです。
Isolated(独立性)とはトランザクション実行中に他のプロセスなどからデータを読み取ろうとしても、処理途中のデータが読み取られないようにする性質のことです。排他制御とは、この独立性を実現するのに用いられる手段の一つです。
Durability(耐久性・永続性)とは、トランザクションが完了時にその結果を記録しシステム障害などが生じても失われることがないという性質のことです。これを実現するためのログをトランザクションログと言います。
SQLite は Android や iOS デバイス、つまりスマホにも対応していますが、スマホはバッテリーで動作し、バッテリーが切れることなんてざらにあるわけで、不意の強制電源断でデータが壊れたり、電源断前の中途半端なゴミデータが残らないようにしないといけません。ノーメンテナンスでソフトウェアを使えるようにしたい場合、データベース管理システムの厳密なトランザクション処理は極めて重要なものである言えます。
複数のデータベースファイルにまたがるトランザクション対応
SQLite の個人的に予想外だった機能の一つは ATTACH DATABASE
を使って複数の SQLite データベースファイルを扱えるということです。単に扱えるだけではなく複数のデータベースファイルにまたがったテーブルの JOIN やトランザクション機能を使うことが出来ます。
明確にこの機能の用途を書いてあるところを見つけてないのですが、これを利用するとデータベースファイルに同時書き込みできるのは一つのプロセスだけという制限を回避できるはずだと考えています。
例えばデータベースファイルをユーザーごとにファイルに分けます。基本的にユーザーは自分のデータベースファイルのみを読み書きします。ファイルが分かれているので異なるユーザーは同時に書き込みが可能です。そしてすべてのユーザーで共有するデータだけを共有データベースファイルに格納することで「共有データベースに書き込むときだけ同時書き込みのプロセスが一つという制限がある」といった感じに軽減できるのではないでしょうか。
自動的に行われる排他制御
他の RDBMS と同じように、トランザクション内で発行された SQL に応じて自動的に排他制御が行われるため、ユーザーは排他制御を自分で行う必要がありません。(例えばロックファイルを使うなどして)自分で排他制御を実装すると簡単なミスでトランザクション処理が正しく実装できてないというバグを入れ込んでしまい、また排他制御は同時に他のプロセスが絶妙なタイミングで読み書きする時に発生するものなので気が付きにくいバグとなってしまいます。
デフォルト(DEFERRED
)ではトランザクション内(BEGIN
開始後)で始めに SELECT
が行われた時に「共有ロック」が掛かり、INSERT
、UPDATE
、DELETE
などの書き込みが行われる時に「排他ロック」相当のロックが掛かります。そして COMMIT
と同時にトランザクション完了です。難しい処理を実装する必要は何もありません。トランザクションの BEGIN
時に IMMEDIATE
や EXCLUSIVE
を指定することでロックが行われるタイミングを変更することも出来ます。排他制御の具体的な処理の流れはこちらを参照してください。
最大 281 テラバイトのデータベースファイル
SQLite は単一のファイルで 281 テラバイトのデータに対応しています。281 ギガバイトではありません。テラバイトです。仮に一レコードが 1KB のデータであれば 3000 億レコード相当です。
民生用の HDD が 10 TB で 2 万円台で買えて 18 TB の HDD も売っている現代においては 281 TB はそんなに大容量とは思えないかもしれませんが、動画などをデータベースに格納しようと考えなければ、このサイズが問題になることはないでしょう。最近ではビッグデータはペタバイト級を指していたりもするようで、そうなれば SQLite では手に負えませんが。
他にも様々な(問題にならないレベルの)制限はあります。詳細は上記のリンク先を参照してください。
単一のデータベースファイルなのでバックアップや管理が簡単
SQLite のデータベースファイルは(ジャーナルなどの一時的なファイルを除いて)単一のデータベースファイルにすべて保存されます。そのためデータをバックアップするなどの管理も簡単になります。
クライアント・サーバー型の RDBMS などではデータベースをメンテナンスすることは当然のように行われるのでデータベースファイルが複数あってもそんなに問題は有りませんが、SQLite が対象としているような小規模でデータベースのメンテナンスを不要にするような場合はデータベースファイルも一つである方が優れているでしょう。ファイル一つをコピーするだけで簡単に他の場所で同じデータベースを再現することが出来ます。
アプリケーション用のファイル形式として使うことができる
★ SQLite As An Application File Format(簡易版)
SQLite のユニークな使い方として、アプリケーション用のファイル形式として使うことが想定されています。アプリケーション用のファイル形式というのは例えば MS Excel の xlsx のファイル形式のようなものです。xlsx のファイルは XML ファイルや埋め込まれている画像ファイルなど複数のファイルを zip 圧縮したものですが、このように複数のファイルを一つの SQLite のデータベースファイルにまとめて保存するというような使い方ができます。
一つのファイルにまとめることで、データを管理しやすくなりますし、個々のデータのみを更新したりトランザクション処理の対象としたり、データベース管理システムが提供する様々なメリットを導入することが出来ます。
「What If OpenDocument Used SQLite?」では Office ソフトのファイル形式として SQLite を使ったらどのようなメリットがあるか?という思考実験が行われています。
ZIP アーカイブの代わりに使える SQLite アーカイブ
特殊なスキーマを定義することで、SQLite データベースファイルを「SQLite アーカイブ」として使うことができます。わかりやすく言えば ZIP アーカイブのような使い方ができるということです。
sqlite3
コマンドを使うことで、まるで ZIP ファイルにアーカイブを追加したり削除したりするようなことができます。SQLite アーカイブを管理するための sqlar
や、FUSE でマウントできる sqlarfs
などのプログラムもあります。
ファイルサイズが気になるかもしれませんがファイルは基本的に圧縮されます。
プログラミング言語に依存せずシェルスクリプトからでも使える
SQLite はプログラミング言語からは独立しており、ほぼすべてのプログラミング言語から SQLite のデータベースファイルを読み書きすることが出来ます。これは複数のプログラミング言語の間でデータを共有して使うことが可能であることを意味しています。ある処理は Python、ある処理は R 言語というように、特定の言語が得意な処理というものがあります。そういった場合でもデータを共有することが簡単にできます。
もし独自のファイル構造やディレクトリ構造を作ってしまった場合、それぞれの言語でそれらを扱うコードを書く必要がありますが、SQLite を使うことでそれが不要となります。
個人的にはシェルスクリプトでも SQLite が使えるということが重要です。シェルスクリプトから使うことができる sqlite3
コマンドが呼び出しているため、sed
や awk
や grep
など Unix コマンドの代わりに sqlite3
コマンドを使うことが出来ます。Unix コマンドは移植性が低く、どの OS でも同じように動くコマンドはなく、さまざまなバッドノウハウが必要になりますが sqlite3
コマンドはどの環境でも全く同じ動きをするため、移植性の問題が発生しません。
さいごに
SQLite はクライアント・サーバー型の MySQL や PostgreSQL を置き換えるものではなく、ファイルアクセスに相当するものですが、完全な RDBMS の機能を持っています。分かりやすいシンプルなコードで高度なデータ管理を行うことができ、十分な機能を備えており、異常なほどテストがされていて、利用実績も信じられないほど多く、将来の互換性や移植性も安心で、性能も信頼性が証明されています。
もちろんすべての場合に SQLite を使う必要があるわけではなく、単純なソフトウェアの場合は普通のファイルで十分だと思います。しかしデータベースが必要となるようなソフトウェアで、普通にファイルを使うだけでは不十分な場合には、独自のファイル・ディレクトリ構造を考えて、それを扱う複雑なプログラムを書くよりも SQLite を使用した方がはるかに楽になるでしょう。
ということで、調査の結果 SQLite はとても凄いデータベース管理システムであることがはっきりしました。
Q.E.D.