1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「1件ずつ書くな」——SQLiteで730倍の差が生まれる理由を3ライブラリで徹底計測した

1
Last updated at Posted at 2026-04-19

📝 3行まとめ

  • SQLiteを「1件ずつ書く」か「まとめて書く」かで、処理速度に最大19.9倍の差が生まれる
  • 読み取りもキャッシュ戦略次第で、素のsqlite3より最大730倍速になる
  • NanaSQLite・DictSQLite・sqlite3の3つを件数別・操作別に計測して傾向を可視化した

本記事のベンチマークはすべて NanaSQLite v1.5.3の最新版(2026年4月時点)、DictSQLite、Python標準sqlite3 を用いて、Windows 11・Python 3.11・SSD環境で実施しました。

はじめに

「SQLiteって遅い」と感じたことはありませんか?

実は多くの場合、SQLiteが遅いのではなく「使い方が遅い」のです。
特に「ループで1件ずつ書く」というコードは、件数が増えるにつれて致命的な速度低下を引き起こします。

今回は以下の3ライブラリを対象に、件数(10〜10,000件)×操作(初期化・書き込み・読み取り)の組み合わせで計測し、どのライブラリのどの操作で差が生まれるのかを徹底的に調べました。

  • sqlite3:Python標準ライブラリ
  • DictSQLite:dict風ラッパー(既存ライブラリ)
  • NanaSQLite:自作の高速KVS風SQLiteラッパー(GitHub / PyPI

計測環境・方法

OS      : Windows 11
Python  : 3.11
ストレージ : SSD
測定方法 : 各操作をREPEAT=5回実行し、mean/min/maxを記録
テスト日 : 2026年4月

テストデータは以下の構造のdictを件数別に生成しています。

{
    f"key_{i}": {
        "name": f"user_{i}",
        "score": i * 1.5,
        "tags": ["admin", "active"],
        "meta": {"created": "2026-04-19", "index": i},
    }
    for i in range(n)
}

計測対象の操作は以下の通りです。

操作 内容
init データベースの初期化・接続
single_write 1件ずつループで書き込み
batch_write 一括書き込み(batch_update / executemany
single_read 1件ずつループで読み取り
batch_read キーリストで一括読み取り
bulk_read 起動時に全データをメモリロードして読み取り

結果①:初期化

n=10
nanasqlite :  4.14ms
dictsqlite : 17.73ms  ← 最大31msの揺れあり
sqlite3    :  2.36ms

sqlite3が最速ですが、DictSQLiteの初期化は不安定で最大440msかかる場合がありました。
NanaSQLiteは件数に関わらず常に約4msで安定しています。

DictSQLiteの初期化は激しく不安定
100件のテストで平均90.87msを記録しましたが、最小値は6.40ms・最大値は413.42msと、実行のたびに大きく変動します。本番環境では予測困難な遅延が発生するリスクがあります。

結果②:書き込み——「1件ずつ」は絶対にやってはいけない

これが本記事の核心です。

シングル書き込み(1件ずつループ)

件数 nanasqlite dictsqlite sqlite3
10 1.10ms 1.50ms 2.75ms
100 9.30ms 13.63ms 3.15ms
500 42.17ms 66.86ms 5.23ms
1,000 85.38ms 126.21ms 7.56ms
5,000 404.62ms 507.13ms 30.31ms
10,000 925.04ms 1021.49ms 59.42ms

chart_single_write.png

10,000件の1件ずつ書き込みは、nanasqliteで約0.9秒、dictsqliteで約1秒かかります。
一方、sqlite3は59msと最速です。シングル書き込みに関しては、素のsqlite3が最も速い。

なぜこうなるのか。nanasqliteやdictsqliteは書き込みのたびにJSONシリアライズや内部処理が走るため、件数に比例してオーバーヘッドが蓄積します。

バッチ書き込み(一括)

件数 nanasqlite (batch_update) sqlite3 (executemany)
10 0.12ms 2.75ms
100 0.44ms 3.18ms
500 1.30ms 4.77ms
1,000 2.36ms 6.98ms
5,000 10.75ms 27.87ms
10,000 38.66ms 52.60ms

chart_batch_write.png

batch_updateを使うと、10,000件でも38msで完了します。
シングル書き込みの925msと比較すると、同じデータ量で約23.9倍速です。

# ❌ これをやると10,000件で約1秒かかる
for key, value in data.items():
    db[key] = value

# ✅ これなら10,000件でも38ms
db.batch_update(data)

大量データには必ずbatch_updateを使ってください
1件ずつの書き込みはトランザクションのコミットが毎回走るため、件数に比例して指数的に遅くなります。100件程度なら気にならなくても、1,000件を超えた時点で体感できる差になります。

結果③:読み取り——キャッシュが730倍の差を生む

シングル読み取り(1件ずつ)

件数 nanasqlite dictsqlite sqlite3
10 0.002ms 0.058ms 0.960ms
100 0.009ms 0.188ms 7.97ms
500 0.041ms 0.904ms 39.39ms
1,000 0.095ms 1.859ms 77.32ms
5,000 0.448ms 24.860ms 390.99ms
10,000 1.201ms 50.265ms 876.14ms

10,000件の読み取りでnanasqliteは1.2ms、sqlite3は876ms
約730倍の差です。

この差の正体はインメモリキャッシュです。NanaSQLiteは一度読み込んだデータをメモリにキャッシュするため、2回目以降のアクセスはディスクI/Oが発生しません。

db = NanaSQLite("data.db")

# 初回:ディスクから読む
val = db["key_1"]

# 2回目以降:メモリキャッシュから返す(超速)
val = db["key_1"]
val = db["key_2"]

bulk_load=True:起動時に全データをメモリへ

# 大量データを頻繁に読む場合はbulk_load=Trueが有効
db = NanaSQLite("data.db", bulk_load=True)
件数 bulk_load=True(mean)
10 2.996ms
1,000 4.233ms
5,000 19.514ms
10,000 39.008ms

chart_single_read.png

起動時に全データをメモリへ展開するため、初期化コストは上がりますが以降の読み取りが最速になります。5,000件以上のデータを頻繁に参照するユースケースで特に効果的です。

まとめ:ライブラリ×操作の使い分け早見表

chart_n10000_all.png

操作 推奨 理由
初期化 NanaSQLite 安定した約4ms。DictSQLiteは不安定
少量シングル書き込み(〜100件) どれでも可 差が小さい
大量シングル書き込み(100件〜) sqlite3 オーバーヘッドが最小
バッチ書き込み NanaSQLite batch_update sqlite3のexecutemanyより1.4倍速
読み取り(頻繁なアクセス) NanaSQLite キャッシュで最大730倍速
読み取り(大量・初回) NanaSQLite bulk_load=True 全ロードで以降の読み取りが最速
型付きデータ NanaSQLite + Pydantic モデルのまま保存・復元できる

おわりに

「SQLiteが遅い」のではなく「使い方が遅い」——この一言に尽きます。

特にシングル書き込みのループは、件数が増えるほど致命的です。100件以上を扱うなら、バッチ書き込みへの切り替えを強く推奨します。

NanaSQLiteは読み取りとバッチ処理に特化した設計になっており、「サクッとデータを永続化してあとは高速に読みたい」というユースケースに最もフィットします。

pip install nanasqlite

🔗 公式サイト: https://nanasqlite.disnana.com/
🐙 GitHub: https://github.com/disnana/nanasqlite

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?