thk*_*ala 26 sql sqlite performance insert
我在我的一个项目中使用SQLite3,我需要确保插入到表中的行对于它们的一些列的组合是唯一的.在大多数情况下,插入的行在这方面会有所不同,但如果匹配,新行必须更新/替换现有行.
显而易见的解决方案是使用复合主键,并使用conflict子句来处理冲突.在此之前:
CREATE TABLE Event (Id INTEGER, Fld0 TEXT, Fld1 INTEGER, Fld2 TEXT, Fld3 TEXT, Fld4 TEXT, Fld5 TEXT, Fld6 TEXT);
Run Code Online (Sandbox Code Playgroud)
成了这个:
CREATE TABLE Event (Id INTEGER, Fld0 TEXT, Fld1 INTEGER, Fld2 TEXT, Fld3 TEXT, Fld4 TEXT, Fld5 TEXT, Fld6 TEXT, PRIMARY KEY (Fld0, Fld2, Fld3) ON CONFLICT REPLACE);
Run Code Online (Sandbox Code Playgroud)
这确实强制执行我需要它的唯一性约束.不幸的是,这种变化也会导致性能损失超出我的预期.我使用sqlite3
命令行实用程序进行了一些测试,以确保我的其余代码中没有错误.测试涉及在单个事务中或在每个1,000行的100个事务中输入100,000行.我得到了以下结果:
| 1 * 100,000 | 10 * 10,000 | 100 * 1,000 |
|---------------|---------------|---------------|
| Time | CPU | Time | CPU | Time | CPU |
| (sec) | (%) | (sec) | (%) | (sec) | (%) |
--------------------------------|-------|-------|-------|-------|-------|-------|
No primary key | 2.33 | 80 | 3.73 | 50 | 15.1 | 15 |
--------------------------------|-------|-------|-------|-------|-------|-------|
Primary key: Fld3 | 5.19 | 84 | 23.6 | 21 | 226.2 | 3 |
--------------------------------|-------|-------|-------|-------|-------|-------|
Primary key: Fld2, Fld3 | 5.11 | 88 | 24.6 | 22 | 258.8 | 3 |
--------------------------------|-------|-------|-------|-------|-------|-------|
Primary key: Fld0, Fld2, Fld3 | 5.38 | 87 | 23.8 | 23 | 232.3 | 3 |
Run Code Online (Sandbox Code Playgroud)
我的应用程序目前执行最多1,000行的交易,我对性能下降15倍感到惊讶.我预计吞吐量下降最多3倍,CPU使用率也会上升,如100k交易案例所示.我想维护主键约束所涉及的索引需要大量的同步数据库操作,因此在这种情况下我的硬盘成为瓶颈.
使用WAL模式确实会产生一些影响 - 性能提升约15%.不幸的是,这本身还不够.PRAGMA synchronous = NORMAL
似乎没有任何影响.
我可能通过增加事务大小来恢复某些性能,但由于内存使用量增加以及对响应性和可靠性的担忧,我宁愿不这样做.
每行中的文本字段具有平均约250个字节的可变长度.查询性能无关紧要,但插入性能非常重要.我的应用程序代码在C中,并且(应该是)可移植到至少Linux和Windows.
有没有办法在不增加事务大小的情况下提高插入性能?SQLite中的一些设置(除了永久强制DB进入异步操作之外的任何东西,或者是在我的应用程序代码中以编程方式)?例如,有没有办法确保行唯一性而不使用索引?
BOUNTY:
通过使用我自己的答案中描述的散列/索引方法,我设法将性能降低到一定程度,以至于我的应用程序可能接受它.但是,似乎随着表中行数的增加,索引的存在使得插入越来越慢.
我感兴趣的是任何技术或微调设置都会提高这个特定用例的性能,只要它不涉及破解SQLite3代码或导致项目变得无法维护.
Gio*_*rgi 15
我已经使用sqlite在运行时插入了数百万行,这是我用来提高性能的方法:
如果您尝试这些,请发布您的测试结果.我相信每个人都会感兴趣.
该ON CONFLICT REPLACE
子句将使SQLite删除现有行,然后插入新行.这意味着SQLite可能会花费一些时间
这是我对它的看法,基于SQLite文档和阅读其他数据库管理系统.我没看过源代码.
SQLite有两种表达唯一性约束的方法:PRIMARY KEY
和UNIQUE
.但是,它们都创建了一个索引.
现在真的很重要的东西...
你做了测试真是太好了.大多数开发人员不这样做.但我认为你的测试结果非常误导.
在您的情况下,将行插入到没有主键的表中的速度并不重要.没有主键的表不满足您对数据完整性的基本要求.这意味着您不能依靠您的数据库来为您提供正确的答案.
如果它没有给出正确的答案,我可以真正,非常快.
要获得有意义的时间插入没有键的表,您需要
当然,这些过程所需的时间也必须考虑在内.
FWIW,我通过在1000个语句的事务中将100K SQL插入语句运行到您的模式中进行了测试,并且只花了30秒.1000个插入语句的单个事务,似乎是您在生产中所期望的,花费了149毫秒.
也许你可以通过插入一个无键的临时表来加快速度,然后从中更新键控表.
归档时间: |
|
查看次数: |
10973 次 |
最近记录: |