0

下面是在 SQLite 中创建两个表和一个视图的代码:

创建表 foo(id TEXT);
在 foo(id) 上创建索引 `foo.index`;
创建表栏(id TEXT);
在 bar(id) 上创建索引 `bar.index`;
CREATE VIEW baz AS SELECT id FROM foo UNION SELECT id FROM bar;

插入 foo 值('123');
插入 foo 值('1123');
插入 foo 值('2123');
插入 foo 值('3123');

插入柱值('44123');
插入柱值('441123');
插入柱值('442123');
插入柱值('443123');

结果EXPLAIN QUERY PLAN SELECT * FROM baz WHERE id='123';是:

扫描表 foo(~1000000 行)
扫描表栏(~1000000 行)
使用 TEMP B-TREE(联合)的复合子查询 2 和 3
扫描子查询 1(~200000 行)

SQL 小提琴:http ://sqlfiddle.com/#!7/b5e79/ 1(使用 WebSQL)

如您所见,当有一个完全可用的索引时,它会进行表扫描。为什么?如何解决此问题以使用索引?

4

1 回答 1

2

这里可能会发生两件事

  • 桌子太小了。只有几行,所有数据都适合一个可以读取的块。所以优化器认为使用索引没有优势。这不太可能,因为所需的所有列都在索引中,因此需要更少的字节来填充。

  • 两者union之间的selects等于union distinct意味着在第一次和第二次选择中重复的所有行都被消除。要找到它们,数据库必须对两个结果集进行排序和合并。如果您union all不需要此排序步骤,因为所有行都将填充where子句放入结果集中。

试试union all。这应该使用索引。

于 2013-10-18T17:41:03.990 回答