SQLite 在廉價 VPS 上的效能表現:真實工作負載基準測試
關於何時該從 SQLite 遷移到像 PostgreSQL 這樣的客戶端-伺服器資料庫,爭論的核心通常在於「規模」。然而,規模往往被誤解為一個二元門檻,而非效能權衡的連續光譜。為了了解 SQLite 究竟在何時達到極限,我們需要超越合成微基準測試,並檢視當工作集(working set)超過可用系統記憶體時的表現。
由 s13k 最近在廉價的 Hetzner CX23 VPS(每月 $4.99 美元)上進行的基準測試,為 SQLite 的能力提供了實際的觀察。透過在僅有 3.7 GB RAM 的機器上測試 6 GB 的資料庫,這些測試迫使引擎必須存取磁碟,模擬了數據增長最終超過硬體資源的真實場景。
測試環境
為了確保結果適用於生產環境,基準測試是在一台低階、共享資源的機器上執行的,其規格如下:
- 硬體: 2 vCPU Intel Xeon Skylake @ 2.1 GHz, 3.7 GiB RAM(無 swap)。
- 作業系統: Debian 13,使用 ext4 檔案系統(
noatime,scheduler=none)。 - 軟體: SQLite 3.53.1,靜態連結至一個 C 基準測試工具。
生產環境現實配置
基準測試並非為了追求極致速度而進行調優,而是使用了一組「符合生產環境現實」的 pragma 設定。此配置在效能與數據安全性之間取得了平衡:
journal_mode = WAL:Write-Ahead Logging 允許讀取者在不阻塞寫入者的情況下進行操作,反之亦然,從而實現更好的併發性。synchronous = NORMAL:這是一個關鍵的權衡。雖然NORMAL並非嚴格的 ACID 持久性(斷電可能會導致 WAL 中最新的交易遺失),但它能防止資料庫損壞,且速度明顯快於FULL。對於需要絕對持久性的應用程式(例如支付處理),FULL仍是必要的選擇。page_size = 8192與cache_size = 256 MiB。mmap_size = 256 MiB。
效能分析:磁碟受限 vs. 快取
本研究的核心在於比較「快取狀態」(資料庫完全符合在 RAM 中)與「磁碟受限狀態」(資料庫大於 RAM)之間的差異。
當資料庫超過 RAM 時
使用 6 GB 的資料庫時,每一次隨機讀取都必須付出 I/O 代價。針對混合 OLTP 工作負載(70% 讀取、25% 更新、5% 插入)的結果顯示,吞吐量為 3,915 ops/s,p99 延遲為 710 µs,p999 延遲為 2.2 ms。
| Phase | Throughput | p50 | p95 | p99 | p999 |
|---|---|---|---|---|---|
| BULK INSERT (10M rows) | 61,300/s | 8 µs | 58 µs | 58 µs | 143 µs |
| SELECT random PK | 3,609/s | 265 µs | 476 µs | 715 µs | 2.3 ms |
| SELECT indexed range scan | 3,477/s | 290 µs | 599 µs | 895 µs | 2.9 ms |
| UPDATE per-row | 2,986/s | 257 µs | 473 µs | 706 µs | 2.2 ms |
| MIXED OLTP | 3,915/s | 257 µs | 455 µs | 710 µs | 2.2 ms |
「引擎天花板」
當工作集縮減至約 246 MB(1M rows)時,資料庫可以輕鬆地放入系統快取中。這揭示了 SQLite 引擎在此特定硬體上的最大潛力,消除了磁碟 I/O 對熱路徑(hot path)的影響。
- 隨機 PK SELECTs: 從 3.6k/s 跳升至 155.8k/s。
- 混合 OLTP: 從 3.9k/s 增加到 53.2k/s。
- 併發讀取: 從 10.3k/s 增加到 104k/s。
關鍵結論與「I/O 崩潰」
比較這兩種狀態可以發現一個殘酷的現實:一旦工作集超過了快取,隨機讀取效能會瞬間崩潰 43 倍。這是 SQLite 應用程式在擴展時的主要瓶頸:並非引擎本身,而是底層的儲存媒介。
然而,即使在最糟的磁碟受限場景下,效能表現依然令人印象深刻。在一個每月 $5 美元的 VPS 上,約 3.9k ops/s 的吞吐量相當於每小時約 1,400 萬次操作。隨著尾端延遲(tail latency)保持在 3 ms 以下,SQLite 對於絕大多數 Web 應用程式來說仍然是一個非常可行的選擇。
結論
對於大多數開發者而言,SQLite 的「規模」極限遠比一般人想像的要來得遠。雖然從 RAM 轉向磁碟時的效能下降非常顯著,但其絕對效能底線仍然足以應付生產環境的負載,即使是在最便宜的硬體上。除非您的應用程式需要對每一次寫入都進行嚴格的 ACID 持久性,或是需要極大的寫入併發量,否則 SQLite 通常綽綽有餘。