MySQL复合索引中的键的高性能排序(WRT Rails多态关联和STI)

jma*_*xyz 7 mysql indexing activerecord ruby-on-rails sti

以前,我在ActiveRecord中询问了关于多态外键的复合索引的问题.我的问题的基础是我的理解,索引应该基于列的基数,并且在Rails的STI类型和多态_type列上通常具有相当低的基数.

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

[owner_id,owner_type]的索引首先放置具有较高基数的字段,而[owner_type,owner_id]将具有较高基数的字段放置在第二位.使用前一个键的查询是否比使用后一个键的查询更高效,或者它们是否同样高效?

我问,因为这对我如何为服务STI模型的表订购复合键有特别的影响.STI Rails查找器几乎总是查询类型列 - 这也是一个通常低基数的列.因此,比其他索引更频繁地查询类型列.如果更经常地查询类型列,那么使用类型前导索引可能是有意义的,因为较少特定的查询可以利用索引的第一部分来产生性能提升.但是,对于高度特定的查询而言,我不会因为性能不利而受到影响.利用索引的高基数部分.

Nic*_*roi 5

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

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

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

在您的情况下,_id列明显更符合定义,因此它们更适合作为键的前缀.

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

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

最后,它真的归结为您的数据集和查询.尝试使用不同复合键排序的多个场景,基准测试,以查看最佳解决方案.另外,不要忘记索引会对表造成写入惩罚.

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

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