【发布时间】:2018-03-20 15:38:49
【问题描述】:
考虑以下示例:
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 表的查询?
【问题讨论】:
标签: sql sqlite query-optimization query-planner