使用较新版本的System.Data.SQLite / sqlite3.dll在SQLite数据库上查询使用子查询大约慢10倍

时间:2013-02-11 13:12:09

标签: .net performance sqlite subquery linqpad

(请参阅下面的更新)

在C#.Net应用程序中查询一个非常简单的大约500,000行的Sqlite数据表(~5秒)时,我遇到了查询性能慢的问题。

我使用LinqPad在完全相同的数据库上尝试完全相同的查询,以及2个数据库浏览器(均基于QtSql),并且运行速度提高了10倍(~0.5secs)。相同的查询,相同的数据库,不同的应用程序,只有我的运行速度不快。

无论是返回值还是仅计数(*),它都可以忽略不计。

我试过了:

  • 为每个.Net 3.5 / 4 / 4.5
  • 构建
  • 为AnyCPU / x86 / x64
  • 中的每一个构建
  • 使用System.Data.Sqlite,sqlite-net,以及通过COM直接访问sqlite3 dll
  • 为每个WPF / WinForms构建
  • 查询的不同变体

这些都不会对查询时间产生任何明显的差异。

我知道使用JOIN重写查询可能有所帮助,但我无法弄清楚为什么同样的查询在LinqPad / Sql浏览器中工作正常但不能从我尝试创建的任何应用程序中工作。我必须遗漏一些非常基本的东西。

示例表:

"CREATE TABLE items(id INTEGER PRIMARY KEY, id1 INTEGER, id2 INTEGER, value INTEGER)"

示例查询字符串(尽管基本上任何使用子查询的查询都需要很长时间):

SELECT count(*) 
FROM items WHERE 
id2 IN 
(
    SELECT DISTINCT id2 FROM items WHERE id1 IN 
    (
        SELECT DISTINCT id1 FROM items WHERE id2 = 100000 AND value = 10
    )
    AND value = 10
) 
AND value = 10 
GROUP BY id2

我知道这可能会使用JOINS和索引来重写以加快速度,但事实仍然是这个查询在其他应用程序中的运行速度要快得多。我在这里想到的是,无论我尝试什么,为什么相同的查询运行得如此之慢?

更新:似乎sqlite的版本与此问题有关。使用旧版System.Data.Sqlite v1.0.66.0,查询就像其他应用程序一样运行,但是使用更新版本的查询速度很慢。我没有确定究竟是什么版本改变了,但我很确定它与底层的sqlite3版本有关,而不是System.Data.Sqlite。如果有人知道可能会发生什么变化会导致子查询在这种情况下放慢速度,或者如果有新设置或某些东西可以使子查询在新版本的sqlite中运行得更快,请告诉我!

同样,查询是一个例子,并不理想,部分冗余......问题更多的是为什么它在一个而不是另一个工作。

提前感谢任何额外的输入!

更新:已解决

请参阅下面的答案。

3 个答案:

答案 0 :(得分:0)

一些建议:

你说你不想重写你的查询,也不想添加索引。这是显而易见的事情。没有任何索引,sqlite必须至少扫描一次500,000行表(或多次扫描)。

根据您在上面的查询,我会在列id1id2中添加索引。

<击> 另一件事是你上面的查询似乎有点多余。也许你有理由,但我不明白为什么查询应该这么复杂。简化查询:

select count(*)
from items
where id2 = 100000 and value = 10

<击>

答案 1 :(得分:0)

尝试

SELECT ID1.id2, count(*) 
FROM items ID2
JOIN items ID1
  on ID2.id2 = ID1.id1
 and ID1.id2 = 100000 
 and ID1.value = 10 
 and ID2.valu3 = 10
group by ID1.id2

答案 2 :(得分:0)

好的结果是与自动索引有关,后者是随SQLite 1.7.0引入的。在我的情况下,在没有索引的这种表上使用子查询意味着SQLite创建自动索引所花费的时间导致了查询遇到的额外开销。

解决方案是使用:

PRAGMA automatic_index=OFF;

在使用“IN”子句的任何查询的开头。

在列上创建索引也可以解决此问题(未经测试),但是在这种特殊情况下,创建索引所需的额外大小/磁盘使用量是不值得的。

这也表明我使用的LinqPad SQLite插件和数据库查看器都基于旧的sqlite版本。

更多信息可在以下网址找到:

http://www.sqlite.org/src/info/8011086c85c6c4040

http://www.sqlite.org/optoverview.html#autoindex

感谢所有回复的人。