indexing - SQLite R*Tree 索引不与 DISTINCT 一起使用
问题描述
在 SQLite 3.20.1 中,我创建了一个 R*Tree 索引 ( dog_bounds
) 和一个临时表 ( frisbees
),如下所示:
-- Changes infrequently and has ~100k entries
CREATE VIRTUAL TABLE dog_bounds USING rtree (
dog_id,
min_x, max_x,
min_y, max_y
);
-- Changes frequently and has ~100 entries
CREATE TEMPORARY TABLE frisbees (
frisbee_id,
min_x, max_x,
min_y, max_y
);
使用此索引进行查询很快,如下所示:
EXPLAIN QUERY PLAN
SELECT dog_id FROM dog_bounds AS db, frisbees AS f
WHERE db.max_x >= f.min_x AND db.max_y >= f.min_y
AND db.min_x < f.max_x AND db.min_y < f.max_y;
0|0|1|SCAN TABLE frisbees AS f
0|1|0|SCAN TABLE dog_bounds AS db VIRTUAL TABLE INDEX 2:D1D3C0C2
但是,如果我 select DISTINCT(dog_id)
,则不再使用索引,并且查询会变慢,即使在以下情况下也是如此ANALYZE
:
EXPLAIN QUERY PLAN
SELECT DISTINCT(dog_id) FROM dog_bounds AS db, frisbees AS f
WHERE db.max_x >= f.min_x AND db.max_y >= f.min_y
AND db.min_x < f.max_x AND db.min_y < f.max_y;
0|0|0|SCAN TABLE dog_bounds AS db VIRTUAL TABLE INDEX 2:
0|1|1|SCAN TABLE frisbees AS f
0|0|0|USE TEMP B-TREE FOR DISTINCT
我怎样才能获得这里使用的 R*Tree 索引?复制狗将是一种耻辱!
解决方案
查询优化器认为不同的执行顺序更容易获得不同的dog_id
值。
将 R-tree 查找移动到子查询中,以便查询优化器被迫分别做这两件事:
SELECT DISTINCT dog_id
FROM (SELECT dog_id
FROM dog_bounds AS db, frisbees AS f
WHERE db.max_x >= f.min_x AND db.max_y >= f.min_y
AND db.min_x < f.max_x AND db.min_y < f.max_y);
查询计划 |--SCAN TABLE dog_bounds AS db VIRTUAL TABLE INDEX 2: |--SCAN TABLE frisbees AS f `--将 TEMP B-TREE 用于 DISTINCT
糟糕,查询优化器太聪明了,把子查询弄平了。但是有一些方法可以禁用它(规则 21):
SELECT DISTINCT dog_id
FROM (SELECT dog_id
FROM dog_bounds AS db, frisbees AS f
WHERE db.max_x >= f.min_x AND db.max_y >= f.min_y
AND db.min_x < f.max_x AND db.min_y < f.max_y
LIMIT -1);
查询计划 |--协同程序 0x892A90 | |--SCAN TABLE frisbees AS f | `--SCAN TABLE dog_bounds AS db 虚拟表索引 2:D1D3C0C2 |--扫描子查询 0x892A90 `--将 TEMP B-TREE 用于 DISTINCT
推荐阅读
- scala - Spark 错误:-“值 foreach 不是对象的成员”
- flutter - Flutter 应用程序中的空值检查运算符错误
- css - 居中使表格变窄
- python - 有没有一种简单的方法可以在不发送邮件的情况下检查邮件后端在 Django 中是否有效?
- swift - XCTestCase - 如何在设置方法中删除应用程序
- php - sqlsrv_fetch_object 返回字符串数据,右截断
- swift - 有没有办法使用 FileManager 和 NSBundle 来获取支持 /Applications 目录中给定类型文件的所有应用程序?
- r - 使用具有变化值的自定义顺序来概括向量的顺序
- c# - 如何序列化名称为“对象”的参数
- mysql - 新数据库未在 localhost:3306 [root] 创建 MySQL 服务器