我会:
- 准备语句(如果你还没有这样做)
- 降低每个事务的INSERT数量(10秒= 500,000听起来很合适)
- 如果可以,使用
PRAGMA locking_mode = EXCLUSIVE;
另外,(我不确定你是否知道)PRAGMA cache_size
以页面为单位而不是MB。确保您将目标内存定义为 PRAGMA cache_size * PRAGMA page_size
或在SQLite> = 3.7.10中,您也可以执行 PRAGMA cache_size = -kibibytes;
。将其设置为1M(illion)将导致1或2GB。
我很好奇cache_size
如何帮助INSERTs...
您还可以尝试基准测试PRAGMA temp_store = FILE;
是否有所不同。
当您的数据库未被写入时:
PRAGMA shrink_memory;
VACUUM;
根据您对数据库的使用情况,这些可能也有所帮助:
PRAGMA auto_vacuum = 1|2;
PRAGMA secure_delete = ON;
我使用以下pragma运行了一些测试:
busy_timeout=0
cache_size=8192
encoding="UTF-8"
foreign_keys=ON
journal_mode=WAL
legacy_file_format=OFF
synchronous=NORMAL
temp_store=MEMORY
测试 #1:
INSERT OR IGNORE INTO test (time) VALUES (?);
UPDATE test SET count = count + 1 WHERE time = ?;
每秒更新次数达到了约109,000次的峰值。
测试#2:
REPLACE INTO test (time, count) VALUES
(?, coalesce((SELECT count FROM test WHERE time = ? LIMIT 1) + 1, 1));
更新速度峰值约为每秒120k。
我还尝试了 PRAGMA temp_store = FILE;
,更新速度下降了约1-2k每秒。
对于一个包含7M条记录的事务,journal_mode=WAL
比其他所有模式都要慢。
我用35839987个记录填充了一个数据库,现在我的设置每批65521个更新需要近4秒钟,但它甚至没有达到16MB的内存消耗。
好的,这里还有一个:
不要在 INTEGER PRIMARY KEY 列上创建索引
当你创建一个 INTEGER PRIMARY KEY 列时,SQLite使用该列作为表结构的键(索引)。这是一个隐藏的索引(因为它不显示在SQLite_Master表中),作用于该列上。在该列上添加另一个索引是不必要的,也永远不会被使用。此外,它还会减慢 INSERT、DELETE 和 UPDATE 操作的速度。
你似乎将PK定义为NOT NULL + UNIQUE。PK 在隐式情况下就是唯一的。