之前,我问过this question about compound indexes on polymorphic foreign keys in ActiveRecord .我的问题的基础是我的理解,即索引应该基于您的列的基数,并且 Rails 的 STI 类型和多态 _type 列的基数通常很低。
承认我的问题的答案是正确的——索引高基数 _id 列和低基数 _type 列是有值(value)的,因为它们一起具有高基数——我的下一个问题是:你应该如何订购复合索引?
[owner_id, owner_type] 的索引将具有较高基数的字段放在第一位,而 [owner_type, owner_id] 将具有较高基数的字段放在第二位。使用前一个键的查询是否比使用后一个键的查询性能更高,还是它们的性能相同?
我问是因为这对我如何为 STI 模型服务的表排序复合键有特殊影响。 STI Rails 查找器几乎总是在类型列上进行查询——这又是一个通常基数较低的列。因此,类型列比其他索引更频繁地被查询。如果更频繁地查询类型列,那么使用类型领先索引可能是有意义的,因为不太具体的查询可以利用索引的第一部分来提高性能。但是,我不会以牺牲高度特定查询的性能为代价来获得更小的好处。利用索引的较高基数部分。
最佳答案
根据我自己的研究(但我不是专家 DBA),我了解到在决定复合键索引的顺序时需要考虑两件事。
首先,关于列的基数,索引通常更擅长搜索基数高的列。所以我倾向于将基数最高的列放在索引中的第一位。作为引用,有一篇标题为 MySQL Query Optimization 的文章上面写着:
Indexes work best for columns that have a high cardinality relative to the number of rows in the table (that is, columns that have many unique values and few duplicates).
在您的情况下,_id
列显然更符合该定义,因此它们更适合作为键的前缀。
要考虑的另一件事是这些索引的可重用性。大多数(如果不是全部)数据库系统允许重复使用复合键的前缀。例如,(owner_id, owner_type)
上的复合键也可用于 owner_id
上的查询,但不能用于 owner_type
上。
因此,根据您在问题中的解释,您最好使用两个索引:(owner_id, owner_type)
上的复合键索引和 (owner_type)
上的复合键索引>.
最后,一切都归结为您的数据集和查询。尝试多种场景,使用不同的复合键排序进行基准测试,看看什么是最佳解决方案。另外,不要忘记索引会对您的表造成写惩罚。
更新:还有另一个关于复合键索引的相当流行的 SO 问题:
关于mysql - MySQL 复合索引中键的高性能排序(WRT Rails 多态关联和 STI),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4947312/