本文へスキップ
ウェブエンジニア問題集
第1章

SQLiteとは何か — サーバー不要のデータベースの仕組みと使いどころ

約10分
この章の目次開く

SQLiteは、アプリケーションに組み込んで使うリレーショナルデータベースです。 MySQLやPostgreSQLのようにデータベースサーバーを起動する必要がなく、1つのファイルがそのままデータベースになります。

「簡易版のデータベース」と紹介されることが多いのですが、実際には世界でもっとも多くデプロイされているデータベースです。スマートフォンのアプリ、Webブラウザ、OS、家電、車載機器のほとんどがSQLiteを内蔵しています。

学習者学習者

サーバーがいらないって、どういうことですか? データベースって、起動してポート番号を指定して接続するものだと思っていました。

先生先生

それはMySQLやPostgreSQLのような「クライアント/サーバー型」の話だね。SQLiteはライブラリとしてアプリの中に入っていて、ファイルを直接読み書きするんだ。

サーバーがない、とはどういうことか

MySQLやPostgreSQLでは、データベースサーバーというプロセスが常に動いています。アプリケーションはネットワーク経由でそのサーバーに接続し、SQLを送り、結果を受け取ります。

SQLiteにはこのサーバープロセスがありません。SQLiteはライブラリであり、アプリケーションのプロセスの中で動きます。SQLを実行すると、そのプロセス自身がデータベースファイルを直接読み書きします。

SQLiteに「接続する」とは、実際には「ファイルを開く」ことです。

この違いが、SQLiteのメリットとデメリットのほぼすべての原因になっています。

観点クライアント/サーバー型SQLite
起動サーバープロセスの起動が必要不要(ライブラリを読み込むだけ)
接続ホスト・ポート・認証情報ファイルパス
ネットワーク越しの利用できるできない
ユーザーごとの権限管理あるない(OSのファイル権限で代替)
運用作業バックアップ・監視・アップデートファイルをコピーするだけ
同時書き込み複数同時に処理できる一度に1つ

データベース = 1つのファイル

SQLiteのデータベースは、テーブルもインデックスもビューもトリガーも、すべて1つのファイルに入っています。

ls -lh
# -rw-r--r--  1 user  staff   32K  mydb.db
bash

このファイルをコピーすれば、それがそのままバックアップです。別のマシンに持っていっても、OSやCPUのアーキテクチャが違っても、同じように読めます。

ファイルパスの代わりに :memory: を指定すると、ディスクを使わずメモリ上だけにデータベースを作れます。プロセスが終了すると消えるため、テストで重宝します。

データを扱うイメージ
SQLiteは「データベースサーバー」ではなく「データベースファイルを扱うライブラリ」です

SQLiteが得意なこと

サーバーがないという特性は、次のような場面で強く効きます。

用途なぜ向いているか
テスト用のDBプロセスごとに使い捨てできる。:memory: なら後片付けも不要
CLIツール・デスクトップアプリユーザーにDBサーバーのインストールを要求しなくてよい
読み取りが中心のWebアプリ読み取りはプロセス内で完結するため非常に速い
設定・キャッシュの保存JSONファイルを自前でパースするよりSQLで扱える
組み込み機器・モバイルアプリメモリと依存が小さい
local-firstなアプリ手元にデータの実体があり、オフラインでも動く

Web開発の文脈では、「PostgreSQLを1台立てるほどではないが、JSONファイルで管理するのは限界」という領域がSQLiteの主戦場です。

SQLiteが苦手なこと

一方で、次のような要件には向きません。理由を理解しておくと、採用の判断が早くなります。

書き込みが同時多発するワークロード SQLiteは、同時に書き込めるプロセスが常に1つだけです。読み取りは並行できますが、書き込みは順番待ちになります。多数のユーザーが同時に投稿するようなサービスでは詰まります。

ネットワーク越しのアクセス SQLiteはファイルを直接読み書きするため、NFSやSMBのようなネットワークファイルシステム上に置くと、ロックが正しく働かずデータが壊れる危険があります。「1台のサーバーの中で完結する」構成が前提です。

ユーザーごとのアクセス制御 GRANT / REVOKE にあたる仕組みがありません。ファイルを読めるプロセスは、そのデータベースの全データを読めます。

学習者学習者

書き込みが1つずつってことは、やっぱり本番では使えないってことですか?

書き込みが「遅い」わけではありません。1回の書き込み自体はむしろ高速で、詰まるのは同時に書き込もうとしたときだけです。1秒あたり数件〜数十件の書き込みであれば問題にならないケースは多く、読み取りが9割を占めるブログ・ドキュメントサイト・社内ツールなどでは十分実用になります。

判断の軸は「アクセス数」ではなく「書き込みの同時実行数」です。ここは トランザクションとWALモード で詳しく扱います。

MySQL・PostgreSQLとの違いを整理する

SQLの文法そのものは、標準SQLをベースにしているためほとんど共通です。SELECT や JOIN の書き方は SQLとデータベースの基礎 で学んだ内容がそのまま使えます。

違いが出るのは、SQLの周辺です。

項目SQLiteMySQL / PostgreSQL
型の扱い緩い(列に宣言と違う型も入る)厳密
真偽値型専用の型がない(0/1で表現)BOOLEAN がある
日付時刻型専用の型がない(TEXT/INTEGERで表現)DATE / TIMESTAMP がある
外部キー制約デフォルトで無効デフォルトで有効
同時書き込み1つ複数
ストアドプロシージャないある
SQLiteでつまずくポイントの大半は、SQLの文法ではなく「型が緩いこと」と「外部キーがデフォルトで無効なこと」です。

この2つはそれぞれ SQLiteの型は緩い と テーブル作成とrowid で扱います。

よくあるハマりどころ

「軽量だから機能が少ない」と思い込む

SQLiteは軽量ですが、機能が乏しいわけではありません。トランザクション、外部キー、ウィンドウ関数、CTE(WITH 句)、JSON関数、全文検索、部分インデックス、生成列など、モダンなSQLの機能を一通り備えています。

先生先生

ウィンドウ関数もCTEも使えるよ。「機能が足りなくて困る」より、「型が緩くて事故る」ほうが圧倒的に多いんだ。

バージョンが古いまま使っている

SQLiteはOSやプログラミング言語のランタイムに同梱されていることが多く、手元のSQLiteが数年前のバージョンのままというケースがよくあります。STRICT テーブルや RETURNING のように後から追加された機能は、古いバージョンでは使えません。

SELECT sqlite_version();
sql

まずこれを実行して、自分が使っているバージョンを把握しておきましょう。

「開発はSQLite、本番はPostgreSQL」で揃えてしまう

手軽さから開発環境だけSQLiteにする構成は一見便利ですが、型の扱いや関数の挙動が違うため、SQLiteでは通ったSQLが本番で落ちることがあります。この構成を取る場合は、CIでは本番と同じDBMSに対してもテストを流すのが安全です。

ちゃんと使うためのポイント

  • SQLiteはサーバープロセスを持たない「組み込み型」のデータベース
  • データベースの実体は1つのファイルで、コピーがそのままバックアップになる
  • 読み取りは並行できるが、書き込みは一度に1つだけ
  • ネットワークファイルシステム上に置くとデータが壊れる危険がある
  • SQLの文法は標準SQLとほぼ共通。違いは型の緩さと外部キーの既定値に集中している
  • SELECT sqlite_version(); で手元のバージョンを最初に確認する

次の章では、SQLiteに付属する sqlite3 コマンドを使って、実際にデータベースを作り、テーブルを確認し、CSVを取り込むところまでを試します。

参考リンク

SQLクイズに挑戦するデータベースの基礎知識を、4択クイズでアウトプットして定着させよう