【问题标题】:what is the best way to add multiple indexes to polymorphic table向多态表添加多个索引的最佳方法是什么
【发布时间】:2013-10-21 19:55:57
【问题描述】:

假设我有类似的多态

| document_id | owner_type | owner_id |
| 1           | Client     | 1        |
| 1           | Client     | 2        |
| 2           | User       | 1        |

我知道我会调用查询以查找 owner_type 和 owner_type + owner_id

SELECT * FROM document_name_ownerships WHERE owner_type = 'Client`
SELECT * FROM document_name_ownerships WHERE owner_type = 'Client` and owner_id = 1

让我们忽略如何索引document_id 我想知道在这种 SQL 场景中索引所有者列的最佳方式(性能)是什么

解决方案 1:

CREATE INDEX do_type_id_ix ON document_ownerships (owner_type, owner_id)

这样我就只有一个索引适用于两种情况

解决方案 2:

CREATE INDEX do_id_type_ix ON document_ownerships (owner_id, owner_type)
CREATE INDEX do_type_ix ON document_ownerships (owner_type)

这样,我将拥有完全匹配我将如何使用数据库的方式的索引。唯一的问题是我只有一个索引时有 2 个索引

解决方案 3:

CREATE INDEX do_id_ix ON document_ownerships (owner_id)
CREATE INDEX do_type_ix ON document_ownerships (owner_type)

单个列索引


根据我在 MySQL 控制台中使用explain 探索的内容,我得到了非常相似的结果,因为它是一个新项目,我没有足够的数据来正确探索这个,所以我可以 100% 确定(即使我填充了数百条记录的数据库)。那么有人可以根据他们的经验给我一些建议吗?

【问题讨论】:

  • 你为什么不尝试任何东西?至少在 SO 上搜索此类问题?这是一个非常非常基本的问题,它有many、many、many 的答案。
  • 谢谢你的建议,是的,我做到了,虽然你是对的,但有很多“像这样”的问题,他们并没有完全问我在问什么,我没有找到令人满意的答案我的问题中列出的解决方案中哪个是最好的

标签: mysql sql indexing


【解决方案1】:

这在很大程度上取决于数据的分布 - 索引只有在存在 good selectivity in the indexed columns 时才有意义。

例如如果owner_type、即Client 和User 只有两个可能的值,并且假设它们分布均匀,那么任何仅在owner_type 上的索引都将毫无意义。在这种情况下,像

这样的查询
SELECT * FROM document_name_ownerships WHERE owner_type = 'Client`;

可能会返回表中很大比例的记录,并且扫描是最好的(尽管我假设您的 真实查询 将加入派生表并过滤派生的特定于表的列,这将是与此非常不同的查询计划。)

因此我会考虑索引

  1. 仅在owner_id 上,假设这本身提供了很好的选择性,
  2. 或者,仅当有证据表明索引 #1 不是选择性的,并且两个字段的组合提供了足够的选择性以保证该索引时,才使用 (owner_id, owner_type) 组合。

【讨论】:

  • 非常好的东西非常感谢你,对于那些眼花缭乱的人,我特别建议在你提供的链接中找到dev.mysql.com/doc/refman/5.5/en/how-to-avoid-table-scan.html。
  • 是的,你是对的,我将主要将此表用作连接的一部分,这是否意味着当我像 SELECT document_names.* FROM document_names INNER JOIN document_name_ownerships ON document_name_ownerships.document_name_id = document_names.id WHERE document_name_ownerships.owner_type = 'Client' AND (document_names.id BETWEEN 1 AND 10) 那样连接 SQL 调用时,查询将被缩小到足够的范围owner_type 的索引有意义吗?
  • 如果 MySql 运行良好,它将首先在派生表上应用选择性过滤器,然后再加入基表并在更小的数据集上应用更多过滤器。确保派生表中返回基表的连接键被索引也很重要(就像您通常使用外键所做的那样)
  • 所以在这种情况下你的意思是document_name_ownerships.document_name_id 我猜。非常感谢斯图尔特,你在这里真的帮助了我。
猜你喜欢
  • 2018-06-07
  • 1970-01-01
  • 2014-09-10
  • 2016-03-08
  • 2012-01-22
  • 2015-03-12
  • 2010-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多