MySQL 索引未在大型数据库中使用
Posted
技术标签:
【中文标题】MySQL 索引未在大型数据库中使用【英文标题】:MySQL indexes not being used in large database 【发布时间】:2018-05-14 17:08:46 【问题描述】:我对一个大表(大约 3700 万行)有一个非常简单的查询。这个查询需要 10 多分钟才能运行,并且应该很快,因为索引是正确构建的(我认为)。我不明白为什么这个查询需要这么长时间。我希望有人可以指导我正确的方向:
查询:
select type_id, sub_type_id, max(settlement_date_time) as max_dt
from transaction_history group by type_id, sub_type_id
创建语句:
CREATE TABLE `transaction_history` (
`transaction_history_id` int(11) NOT NULL AUTO_INCREMENT,
`type_id` int(11) NOT NULL,
`sub_type_id` int(11) DEFAULT NULL,
`settlement_date_time` datetime DEFAULT NULL,
PRIMARY KEY (`transaction_history_id`),
KEY `sub_type_id_idx` (`sub_type_id_id`),
KEY `settlement_date` (`settlement_date_time`),
KEY `type_sub_type` (`type_id`,`sub_type_id`)
) ENGINE=InnoDB AUTO_INCREMENT=36832823 DEFAULT CHARSET=latin1;
解释结果:
id -> 1
select_type -> SIMPLE
table -> transaction_history
type -> index
possible_keys -> NULL
key -> type_sub_type
key_len -> 9
ref -> NULL
rows -> 37025337
filtered -> 100.00
Extra ->
为什么可能的键为 NULL?它说它正在使用索引,但看起来不像。为什么 ref 为空?我怎样才能使这个查询更有效率?索引有问题吗?我是否必须更改任何值 mysql 配置文件?
谢谢
【问题讨论】:
我不完全确定索引对这样的查询有多大帮助;虽然它可能有助于对要聚合的值进行分组;您仍在汇总表中的每个值(它不知道每个组中的最大值在哪里)。如果索引在(type_id, sub_type_id, settlement_date_time)
上,它可能会有所帮助;但我不确定 MAX/MIN 是否可以利用索引,所以这是一个很大的“可能”。
MAX/MIN 可以使用索引@Uueerdo .. 该索引(type_id, sub_type_id, settlement_date_time)
是该查询的覆盖索引
是的,覆盖索引可以使整个表不需要扫描,但它是否可以使 max 不必扫描每个结算日期时间?编辑:好的,发现一些指示 MAX/MIN 的引用通过索引巧妙地处理。 here
感谢 Uueerdo 和 Raymond 的意见。不幸的是,这不起作用。查询仍然需要很长时间才能完成,并且解释仍然显示相同的结果。我将尝试修复索引以防万一出现问题。
@user1783686 - 让我们看看新的CREATE TABLE
、EXPLAIN
,以及说它太慢的结果。
【参考方案1】:
(向已经提供必要INDEX
的两位评论者表示歉意;我会尽量多说一些来证明给出“答案”的合理性。)
使用“复合”(和“覆盖”)索引:
INDEX(type_id, sub_type_id, settlement_date_time)
没有WHERE
,所以不用担心这些列。首先是按GROUP BY
中列出的顺序排列的列,然后是另一列。优化器可能会非常有效地跳过索引。
为什么是NULL
?那么2列索引是无用的。一般来说,如果需要查看超过 20% 的表,最好简单扫描表,而不是在索引 BTree 和数据 BTree 之间跳来跳去。
更多提示:http://mysql.rjweb.org/doc.php/index_cookbook_mysql
【讨论】:
以上是关于MySQL 索引未在大型数据库中使用的主要内容,如果未能解决你的问题,请参考以下文章