以下是在SQLite中创建两个表和一个视图的代码:
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 SELECT id FROM bar; 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 WHERE id='123';
的结果是:
SCAN TABLE foo (~1000000 rows) SCAN TABLE bar (~1000000 rows) COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION) SCAN SUBQUERY 1 (~200000 rows)
SQL小提琴:http://sqlfiddle.com/#!7/b5e79/1(使用WebSQL)
正如您所看到的,当存在完全可用的索引时,它正在进行表扫描。为什么?如何修复此问题以使用索引?
答案 0 :(得分:2)
这里可能会发生两件事
表太小了。只需几行,所有数据都适合无论如何都要读取的块。因此优化器认为使用索引没有任何优势。这不太可能,因为所需的所有列都在索引中,因此需要更少的字节来填充。
两个union
之间的selects
等于union distinct
意味着消除了第一个和第二个选择中重复的所有行。要查找它们,数据库必须对两个结果集进行排序和合并。如果您需要union all
这个排序步骤不是所有行,那么填充where
子句的行将被放入结果集中。
试试union all
。这应该使用索引。