我会:
- 准备陈述(如果你还没有这样做)
- 降低每笔交易的 INSERT 数量(10 秒 = 500,000 听起来合适)
PRAGMA locking_mode = EXCLUSIVE;
如果可以,请使用
另外,(我不确定你是否知道)PRAGMA cache_size
是在页面中,而不是在 MB 中。确保在 as 或 SQLite >= 3.7.10 中定义目标内存,PRAGMA cache_size * PRAGMA page_size
您也可以这样做PRAGMA cache_size = -kibibytes;
。将其设置为 1 M(百万)将导致 1 或 2 GB。
我很好奇如何cache_size
在 INSERT 中提供帮助......
PRAGMA temp_store = FILE;
如果有所不同,您也可以尝试进行基准测试。
当然,只要您的数据库没有被写入:
PRAGMA shrink_memory;
VACUUM;
根据您对数据库的操作,这些也可能有所帮助:
PRAGMA auto_vacuum = 1|2;
PRAGMA secure_delete = ON;
我使用以下编译指示进行了一些测试:
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 = ?;
每秒达到峰值约 109k 更新。
测试#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
它比其他所有更新都慢。
我用 35,839,987 条记录填充了一个数据库,现在我的设置每批 65521 更新需要近 4 秒 - 但是,它甚至没有达到 16 MB 的内存消耗。
好的,这是另一个:
INTEGER PRIMARY KEY 列上的索引(不要这样做)
当您使用 INTEGER PRIMARY KEY 创建列时,SQLite 使用该列作为表结构的键(索引)。这是此列上的隐藏索引(因为它未显示在 SQLite_Master 表中)。不需要在列上添加另一个索引,也永远不会使用。此外,它还会降低 INSERT、DELETE 和 UPDATE 操作的速度。
您似乎将您的 PK 定义为 NOT NULL + UNIQUE。PK 隐含地是唯一的。