8

以前,我问过这个关于 ActiveRecord 中多态外键的复合索引的问题。我的问题的基础是我理解索引应该基于列的基数,并且 Rails 的 STI 类型和多态 _type 列的基数通常很低。

接受我的问题的答案是正确的——这就是索引高基数 _id 列和低基数 _type 列的价值,因为它们在一起具有高基数——我的下一个问题是:你应该如何订购你的化合物索引?

[owner_id, owner_type] 的索引将具有较高基数的字段放在第一位,而 [owner_type, owner_id] 将具有较高基数的字段放在第二位。使用前一个键的查询比使用后一个键的查询性能更高,还是它们的性能相同?

我问是因为这与我如何为服务 STI 模型的表订购复合键有特殊关系。STI Rails 查找器几乎总是在类型列上进行查询——这又是一个通常低基数的列。因此,类型列的查询比其他索引更频繁。如果更频繁地查询类型列,那么使用类型前导索引可能是有意义的,因为不太具体的查询可以利用索引的第一部分来提高性能。但是,我不会因为不利于高度特定查询的性能而降低福利。利用索引的较高基数部分。

4

2 回答 2

5

根据我自己的研究(但我不是 DBA 专家),我了解到在决定复合键索引的顺序时需要考虑两件事。

首先,关于列的基数,索引通常更擅长搜索高基数的列。所以我倾向于将具有最高基数的列放在索引中。作为参考,有一篇题为MySQL 查询优化的文章说:

索引最适用于相对于表中的行数具有高基数的列(即,具有许多唯一值和很少重复的列)。

在您的情况下,这些_id列显然更适合该定义,因此它们更适合作为键的前缀。

要考虑的另一件事是这些索引的可重用性。大多数(如果不是全部)数据库系统允许重用复合键的前缀。例如,复合键 on(owner_id, owner_type)也可以用于查询 onowner_id但不能用于 on owner_type

因此,根据您在问题中的解释,使用两个索引可能会更好:复合键索引 on(owner_id, owner_type)和另一个 on (owner_type)

最后,这一切都归结为您的数据集和查询。尝试多种场景,使用不同的复合键排序进行基准测试,看看什么是最佳解决方案。此外,不要忘记索引会在您的表上产生写入惩罚。

更新:还有另一个相当流行的关于复合键索引的 SO 问题:

什么时候应该使用复合索引?

于 2011-02-13T17:32:00.773 回答
4

TL;DR 把类型放在第一位,然后是 id。

确实,将 id 放在首位会增加第一个决策的基数,从而可以轻松扫描结果记录或应用第二个小索引。但是,如果您曾经单独按类型查询(您将这样做),您将不得不在该类型上维护另一个顶级索引,这会给您的写入性能带来影响。

反过来,[type, id], 将提供一个顶级索引,在仅按类型搜索时可以重用该索引。第二个决定将始终对应于单行,因为 id 在类型上是唯一的,因此您仍然可以确保在索引解析后不会进行行扫描。

IMO 维护另一个索引对写入性能的影响不值得不首先采用类型决策树的边际收益。

于 2016-10-17T21:28:47.280 回答