SQLite 的写入性能与磁盘的性能有很大的关系,例如在 SATA 上可能只有 100 左右,在 SSD 上大概有 1K 左右,如果直接使用 RAMDisk 测试能达到 1W 以上。除此之外,还可以通过一些方法进行相关的优化。

修改配置
在介绍如何修改参数前,提前说明下相关的命令。
PRAGMA 语句是 SQLite 的扩展,主要用于修改数据库的配置等。
- 不同版本的特性可能会被删除或者新增,无法保证其兼容性。
- 未知的命令不会有错误消息出现,它只是简单的忽略。
- 有些 PRAGMA 只在 SQL 执行的部分阶段起作用,例如编译阶段
sqlite3_prepare、执行阶段sqlite3_step。
配置
可以通过 PRAGMA 命令查询或者设置当前系统的配置参数。
----- 要查询当前PRAGMA的值
sqlite> PRAGMA pragma_name;
----- 设置为新值
sqlite> PRAGMA pragma_name = value;
设置模式,可以是名称或等值的整数,但返回的值将始终是一个整数。
常用参数
主要包含了两个:A) synchronous 定义了何时写入磁盘;B) journal_mode 日志写入模式。
synchronous
sqlite> PRAGMA synchronous;
sqlite> PRAGMA synchronous = 2;
用于设置磁盘的写入时机。
0/OFF不进行同步设置,完全由操作系统进行控制;1/NORMALV2默认设置,在关键操作后刷新磁盘,小几率导致数据库损坏;2/FULLV3默认设置,每次关键操作都会刷新磁盘,性能差但是可以保证数据库不损坏。
对于磁盘来说,此时的吞吐量会增加很多,1/2 差异不大。
journal_mode
控制日志文件如何存储和处理的日志模式,可以设置数据库级别。
其中 journal 为数据库事务提供 rollback 操作,当事务写入时,首先写入 journal 文件中,在提交时,根据 journal-mode 来处理 journal 日志文件。
若在提交之前由于断电等原因造成无法提交,当再次启动时,通过 journal 文档做回滚操作,保证数据库的完整性和一致性。
sqlite> PRAGMA journal_mode;
sqlite> PRAGMA journal_mode = mode;
sqlite> PRAGMA database.journal_mode;
sqlite> PRAGMA database.journal_mode = mode;
这里支持五种日志模式:
DELETE默认,在事务结束时,日志文件将被删除;WAL使用 Write Ahead Log;MEMORY日志记录保留在内存中,而不是磁盘上,断电会丢失;OFF不保留任何日志记录;
关于 WAL
在 V3.7.0 版本支持,修改不直接写入数据库文件中,而是直接一个 WAL 的文件中,若事务失败,WAL 记录被忽略;若事务成功,随后在某个 checkpoint 时间点写回数据库。
此时读写、读读可完全并发执行,不会互相阻塞(写之间不能并发)。除了数据库文件,同时会增加 name.db-shm name.db-wal 两个文件。
为了避免读取的数据不一致,查询时也需要读取 WAL 文件,这样的代价就是读取会变得稍慢,但是写入会变快很多。要提高查询性能的话,可以减小 WAL 文件的大小,但写入性能也会降低。
另外,需要注意各个版本间的 WAL 可能不兼容,但是数据库文件是通用的。