使用 EXPLAIN 输出优化慢 MySQL 查询

optimizing a Slow MySQL query using EXPLAIN output

以下查询用了 6.6 秒 运行,并产生了 26 行。

EXPLAIN 结果是两个 'ref' 类型的简单查询,使用键,扫描 23 行和 48 行。

Table f 有 1000 行,table m 有 42000 行。

seltype table type keys                 key                 keylen  ref             rows filtered extra

SIMPLE  f     ref  PRIMARY,             forum_site_id       4       const           23   100.00   Using where; Using temporary; Using filesort
                   forum_site_id,
                   forums_flag_list_new_posts

SIMPLE  m     ref  forum_msg_forum_id,  forum_msg_forum_id  5       locali_db.f.id  48   100.00   Using where
                   forum_msg_status,
                   forum_msg_date   

这里是查询(很简单的一个):

SELECT

    m.id AS msg_id,
    m.public_id AS msg_public_id,
       more fileds of this table ...

    f.id AS forum_id,
    f.public_id AS forum_public_id,
       more fileds of this table ...

FROM

    forum_msgs m
    INNER JOIN forums f ON
        m.forum_id = f.id

WHERE

    f.site_id = 19
    AND f.flag_list_new_posts = 1

    AND m.msg_date >= 1434803744
    AND m.status <> 11

ORDER BY
    m.msg_date DESC

LIMIT 
    100

WHERE 和ORDER BY 子句中的所有字段都是INTEGER 类型并定义为INDEX。字段 forum_id 定义为 FOREIGN KEY。

我很乐意找出可能导致异常表现的原因:)

您的查询基本上是:

SELECT m.*, f.*
FROM forum_msgs m INNER JOIN
     forums f
     ON m.forum_id = f.id
WHERE f.site_id = 19 AND
      f.flag_list_new_posts = 1 AND
      m.msg_date >= 1434803744 AND
      m.status <> 11
ORDER BY m.msg_date DESC
LIMIT 100;

这表明以下索引:forums(site_id, flag_list_new_posts, id)forum_msgs(forum_id, msg_date, status)

我认为没有办法绕过 order by 的文件排序。

INDEX(msg_date)

可能 欺骗优化器从 m 开始并避免对 ORDER BY.

进行排序

(提问性能问题时请提供SHOW CREATE TABLE。)

但是排序并不是代价高昂的部分。代价高昂的部分可能是随机提取到 m。显然缓存是冷的。

EXPLAIN 估计大约有 1000 次读取 (23*48),但这可能会很严重 under/overestimated。如果 m 没有很好地缓存,那可能是 1000 次磁盘命中,这很容易花费 6.6 秒。

如果您使用的是 InnoDB,innodb_buffer_pool_size 应该是 可用 RAM 的大约 70%。

数据库在 RDS 上 运行,具有相当高的 QPS(峰值高达 200)。平均导致 50 IOP/s 到磁盘。将实例存储类型从磁性更改为通用 SSD 解决了这个问题。