Sqlite ORDER BY组的计数很慢

时间:2012-10-14 00:09:15

标签: sqlite group-by sql-order-by

当我向我的查询添加ORDER BY语句时,它变得非常慢。

这是我没有ORDER BY的查询:

SELECT ClientIpAddress, Agentstring, Count(ClientIpAddress) AS Count FROM LogEntries
WHERE SiteIisId = 3 AND DateTime >= '13-09-2012 00:00:00'
GROUP BY ClientIpAddress, Agentstring
LIMIT 5

ET:1ms

现在使用ORDER BY:

SELECT ClientIpAddress, Agentstring, Count(ClientIpAddress) AS Count FROM LogEntries
WHERE SiteIisId = 3 AND DateTime >= '13-09-2012 00:00:00'
GROUP BY ClientIpAddress, Agentstring
ORDER BY Count DESC
LIMIT 5

ET:294 ms

我查询的表包含1.380.855行。

这是我正在使用的索引:

CREATE INDEX "LogEntries_MostActiveClients" ON "LogEntries" ("ClientIpAddress" ASC, "Agentstring" ASC, "SiteIisId" ASC, "DateTime" DESC)

使用EXPLAIN QUERY PLAN Sqlite告诉我它正在使用我的索引扫描表格并使用TEMB B-TREE作为我的订单依据。

我该如何克服这个问题?显然我无法索引Count,那该怎么办?

万分感谢!

2 个答案:

答案 0 :(得分:1)

当您逐步执行结果集时,SQLite会尝试计算尽可能多的值动态

因此,在您的第一个查询中,SQLite永远不需要对表中的所有地址/代理值进行分组;只要它通过某个索引读取了前五个ClientIpAddress / Agentstring组合的记录,就可以停止。

在第二个查询中,这是不可能的:所有地址/代理组必须先完全计算,然后才能对它们进行排序,并选择前五个。

要排序的临时结果中的记录已经在缓存中,并且小于原始表中的数据,因此我猜大多数时间不用于排序,而是分组。

如果排序是问题,并且如果您估计了五个最大计数的大小,则可以尝试添加HAVING "Count" >= some_limit子句以减少要排序的记录数。

您无法避免分组。 您可以尝试的是通过通用优化获得小的改进,例如:

  • 将SQLite的page cache增加到工作集的大小;和
  • 创建一个covering index以避免在表格中进行查找(你已经有了)。

另一种方法是预先计算此查询的值:拥有一个包含Count的单独表,并在添加日志条目时更新它。这将使这些更新变慢,您将不得不确定用于时间戳的粒度。

答案 1 :(得分:0)

使用找到的here SQLite合并来测试您的应用程序。

Richard Hipp最近宣布:

  

我们最近对查询进行了一些重要的增强   SQLite中的优化器。特别是,最新的代码做得更好   识别何时可以通过仔细选择来满足ORDER BY子句   索引和扫描订单,无需进行任何排序。这个   优化可以显着提高查询性能   结果集很大。

电子邮件主题是here