SQLite sqlite3_step()与大数据库挂起

时间:2015-01-04 21:17:24

标签: sql database sqlite subquery

我正在编写一个与嵌入式Objective-C数据库配合使用的小SQLite库。

我使用的SQLite版本为3.7.13(已SELECT sqlite_version()检查)

我的查询是:

SELECT ROUND(AVG(difference), 5) as distance 
FROM (
  SELECT (
    SELECT A.timestamp - B.timestamp 
    FROM ExampleTable as B 
    WHERE B.timestamp = (
      SELECT MAX(timestamp) 
      FROM ExampleTable as C 
      WHERE C.timestamp < A.timestamp
    )
  ) as difference 
  FROM ExampleTable as A 
  ORDER BY timestamp)

基本上它输出按时间戳排序的行之间的平均时间戳差异。

我在35k行的示例数据库上尝试了查询,它运行在大约100ms。到目前为止一切都很好。

然后我在另一个包含100k行的示例数据库上尝试了查询,它在sqlite3_step()处挂起,占用了100%的CPU使用率。

由于我无法使用调试器进入sqlite3_step(),是否有另一种方法可以了解函数挂起的位置或调试日志中的问题是什么?

我还尝试在100k行数据库上运行我的库中的其他查询,但没有问题,但这些都是没有子查询的简单查询也是如此。也许这就是问题?

由于

更新

这是EXPLAIN QUERY PLAN按要求输出的内容:

"1","0","0","SCAN TABLE ExampleTable AS A"
"1","0","0","EXECUTE CORRELATED SCALAR SUBQUERY 2"
"2","0","0","SCAN TABLE ExampleTable AS B"
"2","0","0","EXECUTE CORRELATED SCALAR SUBQUERY 3"
"3","0","0","SEARCH TABLE ExampleTable AS C"
"1","0","0","USE TEMP B-TREE FOR ORDER BY"
"0","0","0","SCAN SUBQUERY 1"

2 个答案:

答案 0 :(得分:1)

可以使用此列上的索引优化按timestamp值查找行:

CREATE INDEX whatever ON ExampleTable(timestamp);

此查询效率低下:ORDER BY不会影响平均值,timestampB中的C值始终相同,因此您可以删除其中一个:

SELECT ROUND(AVG(difference), 5) AS distance 
FROM (
  SELECT timestamp -
         (SELECT MAX(timestamp)
          FROM ExampleTable AS B
          WHERE timestamp < A.timestamp)
         AS difference
  FROM ExampleTable AS A)

答案 1 :(得分:1)

我最终选择了这个解决方案:

CREATE TABLE tmp AS SELECT timestamp FROM ExampleTable ORDER BY timestamp

SELECT ROUND(AVG(difference), 5) 
FROM (
  SELECT (
    SELECT A.timestamp - B.timestamp 
    FROM tmp as B 
    WHERE B.rowid = A.rowid-1
  ) as difference 
  FROM tmp as A 
  ORDER BY timestamp)

DROP TABLE ExampleTable

实际上我走得更远,我只使用这种策略用于大量行(> 40k),因为另一种策略(单一查询)更适合于&#34;小&#34;表。