sql - sqlite选择错误的查询计划

标签 sql sqlite query-optimization query-planner

考虑以下示例:

DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b) WITHOUT ROWID;
WITH RECURSIVE
    cnt(x) AS (VALUES(1000) UNION ALL SELECT x+1 FROM cnt WHERE x<2000)
INSERT INTO t1(a,b) SELECT x, x FROM cnt;
CREATE INDEX t1b ON t1(b);


该查询创建不包含rowid列的表,并在其中插入值(x,x)
1000
ANALYZE;

EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE b BETWEEN 500 AND 2500;

EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE b BETWEEN 2900 AND 3000;


两种情况下的输出均为:0|0|0|SEARCH TABLE t1 USING COVERING INDEX t1b (b>? AND b<?)
但是,使用索引(对于第一个查询)没有意义,因为无论如何我们都必须遍历整个表,因此普通的SCAN TABLE似乎更有效。具有rowid的表正是以这种方式工作:

DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a, b);
WITH RECURSIVE
   cnt(x) AS (VALUES(1000) UNION ALL SELECT x+1 FROM cnt WHERE x<2000)
INSERT INTO t1(a,b) SELECT x, x FROM cnt;
CREATE INDEX t1a ON t1(a);
ANALYZE;

EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500;

EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;


在这种情况下,输出将是:0|0|0|SCAN TABLE t1 0|0|0|SEARCH TABLE t1 USING INDEX t1a (a>? AND a<?)

因此,有人可以解释查询计划程序如何优化WITHOUT ROWID表的查询吗?

最佳答案

两种情况下的输出为:
0 | 0 | 0 |使用覆盖指数t1b(b>?和b <?)搜索表t1
但是,使用索引(对于
第一个查询),原因是无论如何我们都必须迭代
整个表,所以普通的SCAN TABLE似乎更有效。

您错过了COVERING INDEX部分:这意味着它仅使用索引-根本不访问表。
没错,如果需要所有行,则常规索引访问(不带“ COVERING”)可能会比全表扫描慢,但是对于仅索引扫描则不是这种情况。
在此处阅读有关仅索引扫描的更多信息:http://use-the-index-luke.com/sql/clustering/index-only-scan-covering-index
编辑
在SQLite中,无行标识符在其他数据库中是所谓的聚集索引:它们包含所有表列。因此,即使您选择了所有列(例如select *中的列),也无需访问该表。
在此处阅读有关聚簇索引的更多信息:http://use-the-index-luke.com/sql/clustering/index-organized-clustered-index

关于sql - sqlite选择错误的查询计划,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46646259/

相关文章:

sql - 如何统计每个月出现的次数?

java - 如何插入 NULL long 值?

database - SQLite 中的显式锁定机制

sql - SQL查询选择最大/最小的选定的标识符(某种为每个?)

php - 加载 MySQL 查询需要很多时间?如何高效调优数据库

sql - TABLOCK 和 TABLOCKX 定义示例

sql - 如何使此查询返回审核表中的最新记录(MSSQL 2008)

MySQL SELECT From TABLE WHERE FIELD TITLE 不喜欢

php - [MySql]如何从一个表复制一行到另一个表并填充额外的列?

postgresql - 优化拥有近 1.5 亿条记录的 Postgres DB