我有代码(在Linux上使用Perl的DBI,如果重要的话)根据我们定期收到的数据文件更新SQLite数据库表(约4,000万行)。部分代码重复对数据库执行非常简单的选择查询。类似下面的循环在事务中运行。 选择查询通常需要< 0.01秒,但百分之几的时间需要2秒或更长时间。有什么想法吗?这些偶尔的“慢”选择在运行时占主导地位,因此对我来说是个大问题。
while(<UPDATE_FILE>)) {
my ($val4, $val5) = get_values_from_line($_);
my $cmd = "SELECT col1, col2, col3... colN FROM TABLE " .
"WHERE col4 = $val4 AND col5 = $val5 " .
"ORDER BY col2 desc, col3 desc";
execute $cmd;
based on results, insert into or modify the table, or do nothing
}
因此,每次迭代的所有变化都是where子句的细节。我不明白该怎么做以弄清楚发生了什么。
我检查过的事情:
WHERE子句中使用的列有一个有效的索引。
当重新运行相同的代码两次时,并不总是相同的查询速度慢;例如值得责备的不是$ val4和$ val5的特定值。
SELECT返回的行数与查询速度之间没有任何关联。 (行数从不大;&lt; 10)。
我发现在数据库中最后完成的内容和查询速度之间没有明显的联系;特别是,慢查询不一定遵循修改/插入。 (我认为这还没有发生,因为循环是在交易中?)。
$ val4和$ val5可以为null,但这没有区别。
慢查询通常是不连续的。如果你重新运行一个特定的慢查询,它会很快。
我尝试更新时没有其他人使用此数据库。
更新:
EXPLAIN QUERY显示,SQLite出于某种原因选择使用不同的索引,这个索引不适合此查询。当我通过添加“INDEXED BY correct_index”强制查询使用正确的索引运行时,它总是很快。我将尝试运行ANALYZE,看看是否有助于查询优化器。
所以这解决了我当前的问题,但仍然让我感到困惑的是发生了什么。
更新#2:
有些查询仍然随机慢!只是使用新索引,大多数查询都是&lt; 0.001秒,偶尔0.1秒以上。对于这个特定的应用程序来说这是可以容忍的,但可能会给你带来麻烦。