重叠多列索引

时间:2017-07-04 19:01:51

标签: mysql innodb

考虑一个像这样的表(人为的例子;我试图让它模糊地关联):

CREATE TABLE `roles` (
  `host` varchar(50) NOT NULL,
  `port` smallint(6) NOT NULL,
  `user_id` varchar(50) NOT NULL,
  `role` varchar(50) NOT NULL
) ENGINE=InnoDB

典型数据:

INSERT INTO TABLE `roles`
(host, port, user_id, role)
VALUES
('localhost', 8080, 'root', 'admin'),
('localhost', 8080, 'guest', 'readonly');

我知道数据是唯一且非空的:
(host, port, user_id)
我打算使用那个多列索引作为我的主键。

但我喜欢我的SELECTs的覆盖索引优化,它选择所有列。为此,我正在考虑增加更广泛的多列索引:
(host, port, user_id, role)

所以这就是问题......如果我创建了两个索引,(a,b,c)(a,b,c,d):MySQL / InnoDB是否足够聪明,可以将它作为单个索引实现在引擎盖下?
或者它会创造&保持两个指数,浪费空间和时间 - 并且没有注意到(a,b,c,d)(a,b,c)的超集?

我很想避免这个问题而只是制作主键(a,b,c,d),因此只有一个索引。但这似乎是一个次优的主键(它考虑的列数多于保证唯一性所需的列数。)

2 个答案:

答案 0 :(得分:1)

(a,b,c)可能优先使用(由优化程序)而不是(a,b,c,d)因为索引较小。

两者都浪费磁盘空间,并且当缓存两个索引的部分时导致在缓存中浪费空间。这可能导致查询速度变慢。

不要同时拥有两者,而是保持较长的一个。它将处理这两种情况。

如果Instant是一个“大”列,那么带有它的索引将是“大”。在这种情况下,(a,b,c)可能是最好的保留。

另一方面,(a,b,c)和(b,c,a)处理不同的查询,因此可能需要两者。

Cookbook on building indexes

答案 1 :(得分:0)

如果创建拖曳索引So(a,b,c)和(a,b,c,d),查询优化器无法选择更好的..在这种情况下,您应该明确地指定要使用的索引addin using子句加入..

但如果你真的需要,你应该考虑创建不重叠的列索引,例如:

 (a,b,c)   

(d,c,b,a)  

其他组合不是以相同的序列开始的

在这种情况下,索引由匹配等级的查询列

选择

无论如何,您可以在https://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html

找到有用的信息