它在每次执行时创建一个表(只写入,从不读取)并使用以下模式:
(main TEXT NOT NULL PRIMARY KEY UNIQUE,count INTEGER DEFAULT 0);
数据库每秒填充50k个操作.当一个项目已经存在时,它只是使用更新查询更新“count”(相信这称为UPSERT).这些是我的查询:
INSERT OR IGNORE INTO table (main) VALUES (@SEQ); UPDATE tables SET count=count+1 WHERE main = @SEQ;
这样我就可以写得很快,每秒至少有五万个操作.我每500万次操作使用一笔交易.
我不太在乎这个问题的磁盘空间,但是我关心RAM空间.我不想浪费太多的记忆.
使用sqlite3_user_memory()我看到它的内存消耗增长到几乎3GB.如果我通过sqlite3_soft_heap_limit64()将其限制为2GB,则达到2GB时,数据库操作性能将几乎为零.
我不得不将缓存大小提升到1M(页面大小是默认值)以达到期望的性能.
我可以做些什么来缩短内存消耗?
>准备语句(如果你没有这样做)
>降低每个事务的INSERT数量(10秒= 50万个声音适当)
>使用PRAGMA locked_mode = EXCLUSIVE;如果你可以的话
另外,(我不知道如果你知道)PRAGMA cache_size是页面,而不是MB.确保将目标内存定义为PRAGMA cache_size * PRAGMA page_size或在sqlite> = 3.7.10中,还可以执行PRAGMA cache_size = -kibibytes ;.将其设置为1 M(illion)将导致1或2 GB.
我很好奇cache_size如何帮助INSERT,虽然…
如果PRAGMA temp_store = FILE,您还可以尝试和基准测试;有所作为
当然,当你的数据库没有被写入时:
> PRAGMA shrink_memory;
>真空;
根据您在使用数据库的方式,这些可能还有助于:
> PRAGMA auto_vacuum = 1 | 2;
> PRAGMA secure_delete = ON;
我用以下pragmas进行了一些测试:
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的内存消耗.
好的,这是另一个:
Indexes on INTEGER PRIMARY KEY columns (don’t do it)
When you create a column with INTEGER PRIMARY KEY,sqlite uses this
column as the key for (index to) the table structure. This is a hidden
index (as it isn’t displayed in sqlite_Master table) on this column.
Adding another index on the column is not needed and will never be
used. In addition it will slow INSERT,DELETE and UPDATE operations
down.
您似乎将PK定义为NOT NULL UNIQUE. PK是UNIQUE隐含的.