这与 Why is SQLite refusing to use available indexes? 有关
创建数据库的查询是:
CREATE TABLE foo(id TEXT); CREATE INDEX `foo.index` ON foo(id); CREATE TABLE bar(id TEXT); CREATE INDEX `bar.index` ON bar(id); CREATE VIEW baz AS SELECT id FROM foo UNION ALL SELECT id FROM bar; CREATE TABLE bam(id TEXT, value TEXT); INSERT INTO foo VALUES('123'); INSERT INTO foo VALUES('1123'); INSERT INTO foo VALUES('2123'); INSERT INTO foo VALUES('3123'); INSERT INTO bar VALUES('44123'); INSERT INTO bar VALUES('441123'); INSERT INTO bar VALUES('442123'); INSERT INTO bar VALUES('443123');
EXPLAIN QUERY PLAN SELECT * FROM baz LEFT JOIN bam ON baz.id=bam.id WHERE baz.id IN ('123', '234');
的结果是:
SCAN TABLE foo (~1000000 rows) SCAN TABLE bar (~1000000 rows) COMPOUND SUBQUERIES 2 AND 3 (UNION ALL) SCAN SUBQUERY 1 (~2000000 rows) EXECUTE LIST SUBQUERY 4 SEARCH TABLE bam USING AUTOMATIC COVERING INDEX (id=?) (~7 rows)
编辑:有趣的是,如果我这样做了 EXPLAIN QUERY PLAN SELECT * FROM (SELECT * FROM baz WHERE baz.id IN ('123', '234')) AS t LEFT JOIN bam ON t.id=bam.id ;
它仍然不使用索引,但如果我使用 EXPLAIN QUERY PLAN SELECT * FROM baz WHERE baz.id IN ('123', '234');
确实如此。这是怎么回事?
为什么不使用 foo 和 bar 上的索引??它确实使用了没有 JOIN 部分的索引,如链接问题中所示。
SQL fiddle :http://sqlfiddle.com/#!7/32af2/14 (使用 WebSQL)
最佳答案
没有使用索引,因为不需要;他们不会加快查询速度。
在SQLite中,join被实现为嵌套循环join,即数据库遍历一个表的所有记录,并针对每条记录在另一个表中查找匹配的记录。 只有第二个表中的查找需要索引;只遍历第一个表的所有记录不需要索引。
使用内连接,查询优化器可以在循环中选择哪个表是外表或内表(如果只有一个表有索引,它应该是内表)。 但是,对于左外连接,别无选择,左表必须是外表。
要优化左外连接,(仅)右侧的表需要索引。
关于sql - 为什么 SQLite 在添加 JOIN 时拒绝使用可用索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19671738/