SQLite 是目前部署最广泛的数据库引擎,它几乎存在于每一台智能手机和电脑中。与 MySQL、PostgreSQL 等需要独立服务进程的数据库不同,SQLite 是一个嵌入式的、零配置的轻型数据库。本文将探讨 SQLite 在个人项目中的优势场景和性能优化技巧。
一、为什么选择 SQLite 而非 MySQL
对于个人开发者和小型项目而言,SQLite 相比 MySQL 有诸多优势:
- 零配置:不需要安装数据库服务、不需要配置端口、不需要创建用户和密码
- 服务器无关:数据存储在一个 .db 文件中,拷贝文件即完成数据迁移
- 极低资源占用:读写百万级数据时内存占用通常不超过 50MB
- 内置支持:Python、PHP、Node.js 等各种语言都有内置的 SQLite 支持,无需安装额外驱动
- 适合读多写少:SQLite 使用读者-写者锁,对于分析型场景(如我的基金信号分析工具)非常高效
适用场景判断:如果应用每天写入低于 10 万条、并发请求小于 50、数据量在 TB 以下,SQLite 通常是最优解。我的信号分析工具正好符合这个场景。
二、SQLite 与 Python 的无缝集成
Python 标准库自带 sqlite3 模块,无需 pip install 任何东西即可使用:
import sqlite3
# 创建连接(文件不存在会自动创建)
conn = sqlite3.connect('mydata.db')
conn.row_factory = sqlite3.Row # 让查询结果像 dict 一样使用
cursor = conn.cursor()
# 建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS signals (
id INTEGER PRIMARY KEY AUTOINCREMENT,
code TEXT NOT NULL,
date TEXT NOT NULL,
signal_value REAL,
strategy TEXT
)
''')
# 批量插入(事务批量提交性能极高)
data = [('004241', '2026-06-15', 0.85, 'strategy_a')]*1000
cursor.executemany(
'INSERT INTO signals (code, date, signal_value, strategy) VALUES (?,?,?,?)',
data
)
conn.commit()
# 查询
cursor.execute('SELECT * FROM signals WHERE code=?', ('004241',))
for row in cursor.fetchall():
print(row['code'], row['signal_value'])
三、性能优化:WAL 模式与索引
3.1 启用 WAL 模式
SQLite 默认使用 rollback journal 模式,写入时锁定整个数据库。WAL(Write-Ahead Logging)模式允许读写并发,显著提升性能:
cursor.execute('PRAGMA journal_mode=WAL')
cursor.execute('PRAGMA synchronous=NORMAL')
cursor.execute('PRAGMA cache_size=-8000') # 8MB 缓存
cursor.execute('PRAGMA temp_store=MEMORY')
在我的实际测试中,开启 WAL 后批量写入速度提升了约 3 倍,查询延迟降低了 40%。
3.2 索引优化
没有索引的 SQLite 查询会做全表扫描。以下是我在信号数据库中使用的索引策略:
-- 单列索引:加速等值查询
CREATE INDEX IF NOT EXISTS idx_signals_code ON signals(code);
-- 复合索引:加速"按基金+日期范围"的联合查询
CREATE INDEX IF NOT EXISTS idx_signals_code_date ON signals(code, date);
-- 查看索引使用情况
EXPLAIN QUERY PLAN
SELECT * FROM signals WHERE code='004241' AND date > '2026-01-01';
经验法则:WHERE 条件中频繁出现的列、JOIN 的关联列、ORDER BY 和 GROUP BY 的列都应创建索引。但索引不是越多越好,每个索引都会增加写入开销和磁盘空间。
四、多文件数据库的跨库查询
SQLite 原生支持 ATTACH 命令,可以将多个 .db 文件挂载到同一个连接中,实现跨库 JOIN 查询,这在我的项目中非常实用:
conn = sqlite3.connect('main.db')
conn.execute("ATTACH DATABASE 'signals.db' AS sig")
conn.execute("ATTACH DATABASE 'info.db' AS info")
result = conn.execute('''
SELECT s.code, i.name, s.signal_value
FROM sig.signals s
JOIN info.fund_list i ON s.code = i.code
WHERE s.date = '2026-06-15'
ORDER BY s.signal_value DESC
''').fetchall()
五、数据备份与同步策略
SQLite 数据库的备份极其简单——直接复制文件即可。但在生产环境中需要注意以下几点:
- 使用 VACUUM INTO 在线备份:在服务运行中热备份,无需停机
- rsync 增量同步:利用 rsync 的文件块对比能力,只传输变更部分,60MB 数据库实际传输可能只有 5MB
- 避免在同步源执行 VACUUM:VACUUM 会重写整个文件,破坏增量同步的效率
# Python 中执行热备份
conn.execute("VACUUM INTO 'backup_20260615.db'")
# 用 rsync 增量同步到远程服务器
# rsync -av --inplace signals.db user@server:/opt/data/
总结
SQLite 不是"玩具数据库",而是一个经过 20 年打磨、部署量超过一万亿的工业级产品。对于个人开发者而言,选择 SQLite 意味着零运维成本和不俗的性能表现。本文介绍的 WAL 模式、索引策略和跨库查询技巧,构成了一个完整的 SQLite 最佳实践框架,希望能为读者在个人项目中的数据存储选择提供有价值的参考。