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

Posted

技术标签:

【中文标题】使用 rtree 和普通索引的 SQLite 查询很慢【英文标题】:SQLite query using rtree and normal index slow 【发布时间】:2017-05-22 17:18:36 【问题描述】:

我在 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】:

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

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

    纾困,始终进行慢速扫描 仅使用第一个索引,扫描匹配的行 仅使用第二个索引,扫描匹配的行 从两个索引中获取 ID,相交,然后重建所有行

选择最佳策略是查询优化器的任务。如果我们可以预测哪个索引产生较小的结果,通常 2 或 3 是最好的。需要调用ANALYZE时获取统计信息。

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

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

【讨论】:

感谢您提及 EXPLAIN QUERY PLAN。这表明,实际使用的索引。执行缓慢的原因是数据量。我更新了我的问题

以上是关于使用 rtree 和普通索引的 SQLite 查询很慢的主要内容,如果未能解决你的问题,请参考以下文章

从影子表到原始表的 SQLite Rtree 映射 id(s)

sqlite 怎么知道索引在哪个索引btree里

python rtree包查找三维空间下的最近设备

超详细图解!MySQL进阶篇MySQL索引原理

mysql索引小记

Mysql主要索引方式:FULLTEXT,HASH,BTREE,RTREE。