mysql解释类型索引与所有性能问题
Posted
技术标签:
【中文标题】mysql解释类型索引与所有性能问题【英文标题】:mysql explain type index vs all performance question 【发布时间】:2020-12-23 15:45:47 【问题描述】:我有下表:我有 350 万条记录。
CREATE TABLE `video_downloads` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) NOT NULL,
`video_id` bigint(20) NOT NULL,
`download_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3573041 DEFAULT CHARSET=latin1
只有id
和user_id
是indexed
。
这是我的查询:
select max(video_id), user_id
from video_downloads
group by user_id
使用当前的表设置,我运行了这个查询大约需要 10 多分钟。
所以这里是explain
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|----|-------------|-----------------|-------|---------------|---------|---------|-----|---------|-------|
| 1 | SIMPLE | video_downloads | index | | user_id | 8 | | 3562709 | |
"query_block":
"select_id": 1,
"table":
"table_name": "video_downloads",
"access_type": "index",
"key": "user_id",
"key_length": "8",
"used_key_parts": ["user_id"],
"rows": 3562709,
"filtered": 100
然后我删除了运行相同查询的user_id
的索引,我花了大约1.5 s
。
这是没有user_id
索引的explain
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|----|-------------|-----------------|------|---------------|-----|---------|-----|---------|---------------------------------|
| 1 | SIMPLE | video_downloads | ALL | | | | | 3562709 | Using temporary; Using filesort |
"query_block":
"select_id": 1,
"filesort":
"sort_key": "video_downloads.user_id",
"temporary_table":
"table":
"table_name": "video_downloads",
"access_type": "ALL",
"rows": 3562709,
"filtered": 100
我认为我的主要问题是为什么在 user_id
上使用和不使用索引的时间方面存在如此巨大的差异。当user_id
上有索引时,type
是index
,这意味着它正在使用索引但查询很慢。
我对结果有点困惑我想我不明白为什么会这样,我检查了official doc 仍然不完全明白。
更新 我认为主要原因可能是它使用index
数据从磁盘获取行,并且它会一一随机地进行。所以这是从磁盘随机读取的 350 万次。这是我能想到的唯一原因。然而,这会那么慢吗? (超过10 mins
vs 1.5 s
???)。
但是,来自mysql doc
有时 MySQL 不使用索引,即使索引可用。发生这种情况的一种情况是优化器估计使用索引将需要 MySQL 访问表中很大比例的行。
就我而言,MySQL 似乎没有做出正确的决定。我可以看到possible_keys
是null
但key
仍在使用索引,为什么?是因为group by
吗?
【问题讨论】:
我对这些计划有点困惑。他们似乎没有进行聚合。 @GordonLinoff 任何帮助或建议将不胜感激。还是我需要提供更多信息? 在图片中提供信息而不是使用纯文本总是很烦人。 请提供SHOW CREATE TABLE
;当您尝试简化表定义时,有太多微妙的问题被遗漏了。
是 I/O 绑定;我更新了我的答案以部分解释它。该表大约 300MB,对吗?
【参考方案1】:
优化器使用的“统计数据”并不总是完美的。然而,“10 分钟”与“1.5 秒”的对比相当壮观。我想知道是否有外部干扰。哦,正在使用什么引擎?
当它使用单列索引时,它可能不得不在索引和数据之间来回切换,一次获取 350 万行,但是是随机的。
当它进行表扫描(“全部”)时,它还读取了 350 万行,但是是按顺序读取的。但随后它必须进行排序。
Buffer_pool
innodb_buffer_pool_size
的 16M 是问题所在。除非您的机器特别小,否则请将其设置为 RAM 大小的 70% 左右。
10 分钟的查询可能是可靠的 I/O,从表中读取和重新读取数据随机。
在旋转磁盘(HDD,而不是 SDD)上,以 100 块/秒的速度读取 350 万次数据需要几个小时。所以你很幸运在仅 10 分钟内完成。 1.5s 说明了足够大的 RAM 缓存是多么有用。
只需 1.5 秒就可以直接(不是随机)阅读整个表格一次。
【讨论】:
我已经更新了我的问题,你知道为什么会这样吗? @AndySong - 唉,没有明显的解释。还有一个问题:SHOW VARIABLES LIKE 'innodb_buffer_pool_size;
'innodb_buffer_pool_size'
是16777216
@AndySong - 就是这样。什么版本?多少内存?我添加到我的答案中。
而INDEX(user_id, video_id)
应该运行得更快。以上是关于mysql解释类型索引与所有性能问题的主要内容,如果未能解决你的问题,请参考以下文章