【问题标题】:optimizing a Slow MySQL query using EXPLAIN output使用 EXPLAIN 输出优化慢 MySQL 查询
【发布时间】:2015-09-14 08:47:40
【问题描述】:

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

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

表 f 有 1000 行,表 m 有 42000 行。

seltype 表类型键 键 keylen 参考行 额外过滤 SIMPLE f ref PRIMARY, forum_site_id 4 const 23 100.00 使用 where;使用临时的;使用文件排序 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 使用 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。

我很乐意找出导致这种令人发指的表现的原因:)

【问题讨论】:

  • 应避免在第二张桌子上使用 where。

标签: mysql optimization explain


【解决方案1】:

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

【讨论】:

    【解决方案2】:
    INDEX(msg_date)
    

    可能诱使优化器以m 开头并避免对ORDER BY 进行排序。

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

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

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

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

    【讨论】:

    • SHOW CREATE TABLE of 'forum_msgs' 列出以下索引:PRIMARY KEY (id)、UNIQUE KEY uniq_public_id (public_id)、KEY forum_msg_forum_id (forum_id)、KEY forum_msg_status (status), 关键forum_msg_date (msg_date), 关键forum_msg_display_number (display_number), 关键forum_msg_site_id (site_id), 关键forum_msgs_num_clicks (@987654), forum_msgs_parent_id (parent_id)
    • 你用的是什么引擎? public_id 是什么数据类型? f呢?
    【解决方案3】:

    您的查询基本上是:

    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 的文件排序。

    【讨论】:

    • 索引中有两次msg_date没有任何优势。
    • @RickJames。 . .我修复了那个索引。
    猜你喜欢
    • 2016-06-11
    • 2012-08-06
    • 2021-08-09
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 2013-10-11
    相关资源
    最近更新 更多