我想在一个看起来像
的SQLite数据库上运行查询SELECT a,b,c,d FROM data WHERE a IN (1,2,3) ORDER BY b,c
我应该使用什么类型/顺序的索引来启用SQLite(或者更高版本的MySQL)来快速执行此操作?
如何轻松检查查询是否正在增强查询(即如何解释EXPLAIN)?如果我在索引中包含d
,SQLite会更快吗?
编辑: 以下是该表的特征:
a
b
c
PS:当SQLite / MySQL可以使用索引时,是否有可以学习的参考资料?
答案 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, ...)
没有一个索引可以满足这两个要求。