我们来看下面的MySQL表:
CREATE TABLE prices (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
countryCode CHAR(2) COLLATE ASCII_BIN NOT NULL,
productId INT(10) UNSIGNED NOT NULL,
merchantId INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (id),
INDEX (countryCode, productId, merchantId)
) ENGINE=InnoDB;
我将在此表上进行的唯一查找是:
WHERE countryCode = ? AND productId = ?
WHERE countryCode = ? AND productId = ? AND merchantId = ?
因此索引可用于所有查询,这很好。
并非所有查询都包含merchantId
,因此最适合用作复合索引中的最后一列。
现在关于前两列:我永远不会单独countryCode
或productId
单独查找,所以乍一看我会打赌使用索引列订单(countryCode, productId, merchantId)
或(productId, countryCode, merchantId)
在性能方面不应对我的用例产生任何影响,但我没有理论知识支持这一点。
鉴于productId
s与countryCode
s不同,{strong>有任何性能差异(不仅SELECT
,还有INSERT
, UPDATE
和DELETE
速度)改变索引中这两列的顺序,当它们总是一起使用时?
答案 0 :(得分:1)
鉴于条件术语都是等于的,并且这些术语与AND
结合,因此在改变索引中列的顺序方面,性能没有显着差异。
想一下电话簿。如果我让你抬头看“史密斯,约翰”,你抬头看史密斯部分,然后找到约翰。如果书的组织方式不同,按名字和姓氏,你会查找约翰节,然后找到史密斯。无论哪种方式,您都可以轻松缩小搜索范围。
有区别吗?可能略有不同,但它不足以担心。
如果条件不等于,则规则会更改。首先在索引中将列放在等式比较中,然后在范围或不等式条件中放置一列。
您可能也喜欢我的演示文稿How to Design Indexes, Really。还有一个视频录像我在这里发表这个演讲:https://www.youtube.com/watch?v=ELR7-RdU9XU
答案 1 :(得分:1)
你的直觉是正确的。只要你的连接是equi-joins(使用=
),那么你提到的两个索引中的任何一个都应该用于查询。 MerchantId
需要成为继其他两个之后的第三个关键。
可能存在一些非常长的密钥的极端情况,其中CountryCode
和ProductId
之间的排序会产生影响 - 比较长字符串比比较整数需要更长的时间。这些都与您的数据结构无关。
MySQL在查询中使用复合索引实际上有很好的documentation。