使用rtree和普通索引的SQLite查询慢

时间:2017-05-22 17:18:37

标签: sqlite indexing r-tree

我在SQLite表中有地理空间数据,带坐标的名称,并为该位置创建了一个rtree,并在名称列上创建了一个普通索引。

根据此文档使用Rtree: http://www.sqlite.org/rtree.html

当我查询特定区域中的记录时,使用rtree并且它可以快速运行:

SELECT demo_data.* FROM demo_data, demo_index
WHERE demo_data.id=demo_index.id
   AND minX>=-81.0 AND maxX<=-79.6
   AND minY>=35.0 AND maxY>=36.2;

当我只查询名称时,它也会很快,因为使用了名称索引:

SELECT demo_data.* FROM demo_data
WHERE objname="Test"

但是当我将两者结合起来时,它非常慢,似乎整个表都被扫描了:

SELECT demo_data.* FROM demo_data, demo_index
WHERE demo_data.id=demo_index.id
   AND objname="Test"
   AND minX>=-81.0 AND maxX<=-79.6
   AND minY>=35.0 AND maxY>=36.2;

为什么这个组合查询使用两个索引这么慢?

更新

经过对EXPLAIN QUERY PLAN的更多调查后发现,每个条件实际上都使用了索引。但是执行组合查询的时间取决于第一个条件中的记录数。此表demo_data有10mio记录。但如果第一个条件返回大量记录,则组合只会很慢。在这种情况下,有大约1000条记录,objname =“Test”,组合查询需要4秒。 objname =“Test12345”的组合查询,只存在一次,非常快,只有10ms

1 个答案:

答案 0 :(得分:1)

涉及多个索引的查询难以加速,可能需要统计信息,甚至可能来自早期查询。

数据库可以(我不知道SQLite实现了什么),例如:

  1. 纾困,并且总是慢扫描
  2. 仅使用第一个索引,扫描匹配的行
  3. 仅使用第二个索引,扫描匹配的行
  4. 从两个索引获取ID,相交,然后重构所有行
  5. 查询优化器的任务是选择最佳策略。如果我们可以预测哪个指数产生较小的结果,通常2或3是最好的。它需要在调用ANALYZE时获得统计信息。

    使用EXPLAIN QUERY PLAN SELECT ...查看SQLite决定做什么:https://sqlite.org/eqp.html

    您还可以尝试嵌套查询以将优化器推向更好的计划,您应该阅读查询优化器文档:  https://www.sqlite.org/optoverview.html