尽管 EXPLAIN 显示较少的行,但 MySQL 慢查询

Posted

技术标签:

【中文标题】尽管 EXPLAIN 显示较少的行,但 MySQL 慢查询【英文标题】:MySQL Slow Query despite EXPLAIN shows less rows 【发布时间】:2015-03-13 10:54:50 【问题描述】:

我使用的是 mysql 5.1.34,所有表都在 Innodb 引擎中。

我有 3 个表如下:

TableA (1M rows)
-ID (Auto Increment PK)
-TableB_ID
-Date varchar(indexed)
-Other Fields

TableB (60M rows) 
-ID (Auto Increment PK)
-TableC_ID
-Other Fields

TableC (10M rows)
-ID (Auto Increment PK)
-Other Fields

我的目标是加入 3 个与 TableA 中的“日期”匹配的表。 “日期”列被索引,一个简单的 WHERE 子句可以在一秒钟内完成。例如

SELECT * FROM TableA where date = '2015-03-13';
10000 rows in set (0.1 sec)

但是,当我尝试使用下面的 SQL 连接 TableB 和 TableC 时,过程变得非常缓慢。

SELECT A.*, C.Something FROM TableA A JOIN TableB B on A.TableB_ID = B.ID JOIN TableC C on B.TableC_ID = C.ID WHERE A.date = '2015-03-13';
10000 rows in set (20 sec)

我尝试使用 EXPLAIN 命令解决缓慢问题,输出如下。

可能是什么原因?请帮忙!

【问题讨论】:

A.TableB_IDB.TableC_ID 是否已编入索引? @AbhikChakraborty 已编辑。抱歉,是的,A.TableB_ID 和 B.TableC_ID 都已编入索引。 @KarolyHorvath 磁盘搜索是什么意思? @AbhikChakraborty 。 . . BC 中的 id 列是主键,正如 OP 所说和 explain 中所示。不需要额外的索引。 @PeirHwa.Soo 。 . .第二次运行查询需要多长时间?您可能遇到冷缓存问题,将大约 20,000 页从磁盘读取到内存需要时间。 【参考方案1】:

正如我所说,这可能是磁盘查找问题。正如您所测量的,一旦记录在内存中,查询速度很快,对我来说,这证实了问题。

从磁盘中获取随机位置大约需要 10 毫秒,因为磁盘磁头必须移动。相关记录可能聚集在磁盘上,服务器必须做大约。 20 秒/10 毫秒 = 20.000 次搜索。

有几个明显的方法:

使用 SSD。不求。 为服务器添加足够的 RAM 以避免磁盘访问,或者为这些查询使用专用服务器(16GB 看起来绰绰有余(虽然我不知道记录的大小)所以我猜还有其他常用的巨大的桌子)。 按日期缓存结果 - 并将其存储在数据库中 (memcached/redis/..)。如果旧日期的记录是静态的,这可能会非常有效,因为您不必担心缓存失效。

无论如何,做一些粗略的计算并弄清楚内存需求可能是个好主意。

【讨论】:

【参考方案2】:

你没有提供SHOW CREATE TABLE,漏掉了很多重要信息,但我会做一些猜测。

您真的在获取 10K 行吗?你打算怎么处理他们所有人?获取这么多行需要时间。

如果您使用的是 MyISAM,那么 B 将从 INDEX(ID, TableC_ID) 中受益匪浅。 InnoDB 不应该从中受益,除非表非常“宽”。

SHOW VARIABLES LIKE '%buffer%';你有多少内存?

查询缓存是否正在使用中?如果是这样,那就可以解释为什么第二次这么快了。大多数生产系统都认为关闭 QC 会更好。

【讨论】:

以上是关于尽管 EXPLAIN 显示较少的行,但 MySQL 慢查询的主要内容,如果未能解决你的问题,请参考以下文章

20180625-mysql优化

MySQL命令 Explain参数说明

MySQL explain 详解

MySQL Explain 的行数与慢查询日志不同

MySQL的Explain关键字查看是否使用索引

MySQL的Explain关键字查看是否使用索引