虽然 SQLite 非常轻量,但在处理大规模数据写入或复杂查询时,如果不进行合理优化,性能可能会成为瓶颈。本文将深入几个关键的性能调优参数。
SQLite 默认是自动提交模式,每条 INSERT 语句都隐式地开启并提交一个事务。在插入大量数据时,这会导致磁盘频繁 fsync,性能极差。
优化方法:显式开启事务,将成千上万条语句打包在一起提交。
# Python 示例 cursor.execute("BEGIN TRANSACTION") for data in huge_list: cursor.execute("INSERT INTO table VALUES (?)", data) cursor.execute("COMMIT")
经验表明,批量提交可以将插入速度从每秒几十条提升到每秒数万甚至数十万条。
SQLite 提供了一系列运行时配置(PRAGMA),可以根据应用场景调整行为:
PRAGMA synchronous = OFF:关闭同步。写入数据时不再等待数据真正落盘再返回。风险:如果操作系统崩溃或断电,数据库可能损坏。适用于临时数据或可重建的数据(如缓存)。
PRAGMA journal_mode = WAL:强烈推荐。开启预写日志(Write-Ahead Logging,WAL)模式。WAL 模式允许读写并发(读操作不阻塞写,写操作不阻塞读),且比默认的 DELETE 模式有更少的磁盘 I/O 操作。
PRAGMA cache_size = -20000:设置缓存大小。负数表示使用内存页的 KB 数,如 -20000 表示 20MB 缓存。适当增大缓存可以减少磁盘读取。
索引是把双刃剑。在 SQLite 中,索引维护的成本在写操作时尤为明显。
覆盖索引:如果查询只需要 SELECT 索引列,SQLite 可以直接从索引返回数据,无需回表读取原始数据。
避免冗余索引:SQLite 的查询优化器能力有限,复合索引的字段顺序很重要。例如索引 (a, b) 可以支持 WHERE a = ?,但无法高效支持 WHERE b = ?。
延迟创建索引:在批量导入数据前,先删除索引,导入完成后再重建索引。因为维护索引的开销远大于重建的开销。
页面大小在创建数据库时确定(默认通常是 4096 字节)。对于存储大量 BLOB 数据(如图片、文件)的场景,使用较大的页面大小(如 8192 或 16384)可以减少跨页访问的次数,提升性能。
-- 创建数据库时设置 PRAGMA page_size = 8192;