【问题标题】:Why is SQLite refusing to use available indexes?为什么 SQLite 拒绝使用可用的索引?
【发布时间】:2013-10-27 14:23:42
【问题描述】:

下面是在 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)

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

【问题讨论】:

  • This SQL Fiddle 显示正在使用的索引?这是您用来测试的确切脚本吗?
  • 您的 SQLFiddle 向我展示了与我输出相同的内容...没有使用索引。 (是的,这就是我测试它的确切代码)
  • 不在我的浏览器中,它显示SCAN TABLE foo USING COVERING INDEX foo.index (~1000000 rows) 作为第一步显示它正在使用foo.Index
  • 嗯,好的,WebSQL 不使用索引,但 SQL.js 使用。
  • 奇怪的是,UNION ALL 将使用索引...

标签: sql sqlite


【解决方案1】:

这里可能会发生两件事

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

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

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

【讨论】:

    猜你喜欢
    • 2013-11-09
    • 1970-01-01
    • 2017-03-15
    • 2013-11-15
    • 1970-01-01
    • 2014-10-05
    • 1970-01-01
    • 1970-01-01
    • 2012-04-16
    相关资源
    最近更新 更多