我有大约20,000个要插入表格的项目列表(其中约有50,000行)。这些项目中的大多数更新现有行中的某些字段,少数将插入全新的行。
我为每个项目访问数据库两次。首先是一个选择查询,检查该行是否存在。接下来,我根据select查询的结果插入或更新一行。我在更新/插入后立即提交每个事务。
对于前几千个条目,我每秒通过大约3或4个项目,然后它开始变慢。到最后,每次迭代需要超过1/2秒。为什么它会放慢速度?
我的平均时间是:整个运行时间为0.5秒,每个选择查询分为.18s,每次插入/更新分为.31s。最后的0.01是由于在进入数据库之前解析数据的几个未测量的进程。
更新
我已经将所有提交评论为测试并且没有变化,所以不是这样(尽管如此,还是欢迎对最佳提交的任何想法。)
关于表格结构: 每行有20列。前四个是TEXT字段(全部设置为第一个插入),16个是REAL字段,其中一个输入初始插入语句。
随着时间的推移,'杰出的'REAL字段将填充我正在尝试优化的过程。
我没有明确的索引,但其中一个字段是每行的唯一键。
我应该注意到,随着数据库变得越来越大,SELECT和UPDATE查询花费的时间越来越多,SELECT操作的性能特别显着下降。
我最初认为这可能是SQLITE的某种结构性问题(无论这意味着什么),但是无法在任何地方找到任何表明该程序存在自然限制的文档。
现在数据库大约有60个megs。
答案 0 :(得分:5)
我认为你的瓶颈是每次插入/更新/ avec提交:
我在更新/插入后立即提交每笔交易。
要么停止这样做,要么至少切换到WAL journaling;看到我的答案为什么: SQL Server CE 4.0 performance comparison
如果您有主键,可以使用INSERT INTO使用ON CONFLICT子句来优化选择:
http://www.sqlite.org/lang_conflict.html
编辑:之前我打算写“如果你有主键”而不是外键;我修好了。
答案 1 :(得分:2)
编辑:对我感到羞耻。我误解了这个问题,并且不知怎么理解这是针对 mySQL 而不是 SQLite ......哎呀。 除了获得有关更新DBMS的一般想法之外,请忽略此响应。正如sixfeetsix' response中指出的那样,OP问题的可能解决方案是过于频繁的提交。
一个合理的解释是表格碎片 您可以经常defragmenting the table验证这一事实,并检查性能是否会返回到每秒3或4项的速率。 (BTW,先验相对较慢,但可能依赖于硬件,数据架构和其他细节。)当然,您需要考虑碎片整理所需的时间,并将此与缓慢更新所损失的时间相平衡速率以找到碎片整理的最佳频率。
如果有效地导致减速,至少部分是由碎片造成的,您还可以考虑按特定顺序执行更新。如果不了解整体和数据统计配置文件的架构细节,就很难更具体,但是碎片确实对数据库发生各种变化的顺序很敏感。
提高整体更新性能的最终建议是(如果可行)删除表上的一些索引,执行更新,并重新创建索引。这种反直觉的方法适用于相对较大的更新,因为重新创建新索引的成本通常低于在更新过程中维护它们的累积成本。