Ped*_*ves 15 c sqlite performance memory-consumption
我正在寻找在我的应用程序中减少SQLite3的内存消耗的方法.
在每次执行时,它都会创建具有以下模式的表:
(main TEXT NOT NULL PRIMARY KEY UNIQUE,count INTEGER DEFAULT 0)
Run Code Online (Sandbox Code Playgroud)
之后,数据库每秒充满50k操作.只写.
当一个项目已经存在时,它会使用更新查询更新"count"(我认为这称为UPSERT).这些是我的疑问:
INSERT OR IGNORE INTO table (main) VALUES (@SEQ);
UPDATE tables SET count=count+1 WHERE main = @SEQ;
Run Code Online (Sandbox Code Playgroud)
这样,每个事务有500万次操作,我可以非常快速地写入数据库.
我真的不关心这个问题的磁盘空间,但我有一个非常约束的RAM空间.因此,我不能浪费太多记忆.
使用sqlite3_user_memory()通知其执行期间内存消耗增长到近3GB.如果我通过sqlite3_soft_heap_limit64()将其限制为2GB,则当达到2GB时,数据库操作性能几乎降至零.
我不得不将缓存大小提高到1M(默认页面大小)以达到理想的性能.
我该怎么做才能减少内存消耗?
Pei*_*Zhu 11
似乎高内存消耗可能是由于太多操作集中在一个大事务中.尝试像每1M操作一样提交较小的事务可能会有所帮助.每个事务5M操作将消耗许多内存.
但是,我们会平衡操作速度和内存使用情况.
由于较小的交易没有帮助,PRAGMA shrink_memory可能是一种选择.
使用sqlite3_status()with SQLITE_STATUS_MEMORY_USED来跟踪动态内存分配,并找到该点.
我会:
PRAGMA locking_mode = EXCLUSIVE;,如果你能另外,(我不确定您是否知道)PRAGMA cache_size以页为单位,而不是以 MB 为单位。确保在 asPRAGMA 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;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;
Run Code Online (Sandbox Code Playgroud)
INSERT OR IGNORE INTO test (time) VALUES (?);
UPDATE test SET count = count + 1 WHERE time = ?;
Run Code Online (Sandbox Code Playgroud)
每秒达到约 109k 更新的峰值。
REPLACE INTO test (time, count) VALUES
(?, coalesce((SELECT count FROM test WHERE time = ? LIMIT 1) + 1, 1));
Run Code Online (Sandbox Code Playgroud)
达到每秒约 12 万次更新的峰值。
我也尝试过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 是唯一的。
| 归档时间: |
|
| 查看次数: |
14840 次 |
| 最近记录: |