使用 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 查询很慢的主要内容,如果未能解决你的问题,请参考以下文章