orderby / SQL中的查询是什么类型的索引?

时间:2014-09-10 08:39:32

标签: sql sqlite indexing

我想在一个看起来像

的SQLite数据库上运行查询
SELECT a,b,c,d FROM data WHERE a IN (1,2,3) ORDER BY b,c

我应该使用什么类型/顺序的索引来启用SQLite(或者更高版本的MySQL)来快速执行此操作? 如何轻松检查查询是否正在增强查询(即如何解释EXPLAIN)?如果我在索引中包含d,SQLite会更快吗?

编辑: 以下是该表的特征:

  • 10.000.000行
  • 60个不同a
  • 6.000.000 distinct b
  • 2.000 distinct c
  • 无约束
  • 该表是我的个人分析数据;它只写一次,然后只读

PS:当SQLite / MySQL可以使用索引时,是否有可以学习的参考资料?

4 个答案:

答案 0 :(得分:4)

如果且仅当IN (1,2,3)是常量列表(总是相同的值)时,您可以使用partial index,如下所示:

CREATE INDEX so ON data (b,c) WHERE a IN (1,2,3)

然后运行您的查询会提供此计划(explain query plan select...):

0|0|0|SCAN TABLE data USING INDEX so
0|0|0|EXECUTE LIST SUBQUERY 1

注意:没有ORDER BY操作。

作为反测试,让我们删除索引并将其替换为:

CREATE INDEX so ON data (a,b,c);

新的执行计划是:

0|0|0|SEARCH TABLE data USING INDEX so (a=?)
0|0|0|EXECUTE LIST SUBQUERY 1
0|0|0|USE TEMP B-TREE FOR ORDER BY

您现在看到排序操作了吗?

我没有生成任何有意义的测试数据(只是一个空表)来验证执行速度的提高。但我想你应该在创建索引后马上看到它。

另请注意,自SQLite 3.8.0(2013-08-26发布)

以来,仅支持部分索引

答案 1 :(得分:1)

要考虑的一件小事是:如果您对a in (1, 2, 3)进行过滤,会找到多少行? 如果这是表的很大一部分,可能已经高达15%左右,使用索引甚至可能会降低性能。

将其与图书索引进行比较。假设索引已完成,这意味着所有单词都被索引。如果您正在寻找"和"的出现,并且您使用此索引,则您无法从索引跳转到文本并返回。只需从封面到封面阅读本书,扫描"和"肯定会是更快的选择。

它并不清楚盈亏平衡点在哪里,因为它取决于很多因素。但它低于大多数人的想法。 (我已经提到了15%,根据我的经验,这是一个很好的经验法则)

如果可以省略排序,则仍然可以使用索引。在这种情况下,树索引将具有列(b, c, a)。 (哈希索引不会有帮助)。 根据数据类型和更新频率,您甚至可以考虑使用(b, c, a, d)作为索引。 DBMS只需要进行索引扫描,而不是表扫描。 (如果d很大,它就不会帮助太多并破坏大量空间;如果d经常更新,那也可能是一个坏主意,因为它会使工作量增加一倍更新)。

物理数据库设计通常是找到正确妥协的问题。

好的,我的很多写作在您编辑后不再适用。我仍然觉得答案可能会给你一些思考的东西。

答案 2 :(得分:1)

以下索引可帮助您快速获取记录 - 当然,前提是dbms认为索引的使用比全表扫描更快。例如,如果它认为in(1,2,3)将获得表中90%的记录,它应该避免使用索引而只是扫描整个表。

CREATE INDEX idx ON data(a);

以下索引可帮助您快速获取记录,甚至可以快速对其进行排序。同样,如果dbms认为根本不使用索引,则不会使用此索引。但是更有可能使用索引,因为dbms不仅获取了要访问的记录的信息,而且它们已经对它们进行了排序。

CREATE INDEX idx ON data(a,b,c);

以下索引可帮助您快速获取记录并快速对其进行排序,甚至根本无需访问该表。这里所有数据都存在于索引中,因此dbms没有理由不使用索引。它就在那里:获取有用数据的标准,它的排序,甚至数据本身已经存在。

CREATE INDEX idx ON data(a,b,c,d);

答案 3 :(得分:0)

  • 要对a in (1,2,3)进行过滤,您需要一个以(a, ...)
  • 开头的索引
  • 要对b, c进行排序,您需要一个以(b, c, ...)
  • 开头的索引

没有一个索引可以满足这两个要求。