重叠的多列索引
Overlapping multi-column indices
像这样考虑一个 table(人为的例子;我试图让它变得模糊 relatable):
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)
我打算使用那个多列索引作为我的主键。
但我 也 喜欢我的 SELECT 的覆盖索引优化,select 所有列。为此,我正在考虑在以下位置添加更广泛的多列索引:
(host, port, user_id, role)
所以问题来了……如果我创建两个索引,(a,b,c)
和 (a,b,c,d)
:MySQL/InnoDB 是否足够聪明,可以在后台将其实现为单个索引?
或者它会创建和维护两个索引,浪费 space 和时间——并且没有注意到 (a,b,c,d)
是 (a,b,c)
的超集?
我想避免这个问题,只做主键(a,b,c,d)
,这样只有一个索引。但这似乎是一个次优的主键(它考虑了比保证唯一性所需的更多的列)。
如果您创建两个索引,那么 (a,b,c) 和 (a,b,c,d) 查询优化器无法选择更好的.. 在这种情况下,您应该明确指定要使用的索引加入 using 子句加入 ..
但如果你真的需要,你应该考虑创建不重叠的列索引,例如:
(a,b,c)
和
(d,c,b,a)
其他不以相同序列开始的组合
在这种情况下,索引是根据查询列的匹配等级来选择的
无论如何你可以在这里找到有用的信息https://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html
(a,b,c) 可能比 (a,b,c,d) 优先使用(优化器),因为索引较小。
同时拥有这两个索引会浪费磁盘 space,并且当缓存两个索引的一部分时会导致缓存中的空间浪费。这会导致查询变慢。
与其同时拥有两者,不如保留较长的一个。它会处理这两种情况。
如果 d
是一个 "big" 列,那么它的索引将为 "big"。在这种情况下,(a,b,c) 可能是首选。
另一方面,(a,b,c) 和 (b,c,a) 处理 不同的 查询,因此您 可能 两者都需要。
像这样考虑一个 table(人为的例子;我试图让它变得模糊 relatable):
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)
我打算使用那个多列索引作为我的主键。
但我 也 喜欢我的 SELECT 的覆盖索引优化,select 所有列。为此,我正在考虑在以下位置添加更广泛的多列索引:
(host, port, user_id, role)
所以问题来了……如果我创建两个索引,(a,b,c)
和 (a,b,c,d)
:MySQL/InnoDB 是否足够聪明,可以在后台将其实现为单个索引?
或者它会创建和维护两个索引,浪费 space 和时间——并且没有注意到 (a,b,c,d)
是 (a,b,c)
的超集?
我想避免这个问题,只做主键(a,b,c,d)
,这样只有一个索引。但这似乎是一个次优的主键(它考虑了比保证唯一性所需的更多的列)。
如果您创建两个索引,那么 (a,b,c) 和 (a,b,c,d) 查询优化器无法选择更好的.. 在这种情况下,您应该明确指定要使用的索引加入 using 子句加入 ..
但如果你真的需要,你应该考虑创建不重叠的列索引,例如:
(a,b,c)
和
(d,c,b,a)
其他不以相同序列开始的组合
在这种情况下,索引是根据查询列的匹配等级来选择的
无论如何你可以在这里找到有用的信息https://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html
(a,b,c) 可能比 (a,b,c,d) 优先使用(优化器),因为索引较小。
同时拥有这两个索引会浪费磁盘 space,并且当缓存两个索引的一部分时会导致缓存中的空间浪费。这会导致查询变慢。
与其同时拥有两者,不如保留较长的一个。它会处理这两种情况。
如果 d
是一个 "big" 列,那么它的索引将为 "big"。在这种情况下,(a,b,c) 可能是首选。
另一方面,(a,b,c) 和 (b,c,a) 处理 不同的 查询,因此您 可能 两者都需要。