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

标签 mysql ruby-on-rails activerecord indexing sti

之前,我问过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 问题:

When should I use a composite index?

关于mysql - MySQL 复合索引中键的高性能排序(WRT Rails 多态关联和 STI),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4947312/

相关文章:

mysql - 分组、计数和连续圈数

database-design - 哪种MySQL表类型适合在线图书馆和评论?

ruby-on-rails - 真实逻辑。什么哈希函数?

ruby-on-rails - 如何从 ActiveRecord 模型中提取常见的 named_scopes

ruby-on-rails - 可以使用 Rails ActiveRecord #save 方法更新现有记录吗?

php - 结果在 MySQL 前端给出 undefined

php - 连接表时,某些条目的日期列为 NULL

ruby-on-rails - 与 unicorn/thin/puma/etc 相比 passenger 5 的性能

ruby-on-rails - 如何在 couchdb View 中使用 OR

sql - 棘手的事件记录关系——多态双向自引用