【问题标题】:Same MySQL query runs much slower in 5.6 than in 5.1相同的 MySQL 查询在 5.6 中运行比在 5.1 中慢得多
【发布时间】:2015-04-02 00:24:20
【问题描述】:

我遇到了一个奇怪的问题,在我们将数据库从 MySQL 5.1.73 升级到 5.6.23 后,这个特定的 MySQL 查询的运行速度会慢近 50 倍。

这是 SQL 查询:

SELECT `companies`.*
FROM   `companies` 
   LEFT OUTER JOIN `company_texts` 
                ON `company_texts`.`company_id` = `companies`.`id` 
                   AND `company_texts`.`language` = 'en' 
                   AND `company_texts`.`region` = 'US' 
   INNER JOIN show_texts 
           ON show_texts.company_id = companies.id 
              AND `show_texts`.`is_deleted` = 0 
              AND `show_texts`.`language` = 'en' 
              AND `show_texts`.`region` = 'US' 
   INNER JOIN show_region_counts 
           ON show_region_counts.show_id = show_texts.show_id 
              AND show_region_counts.region = 'US' 
    WHERE  ( ( `companies`.`id` NOT IN ( '77', '26' ) ) 
     AND ( `company_texts`.is_deleted = 0 ) 
     AND `companies`.id IN (
        SELECT DISTINCT show_texts.company_id AS 
                                id 
                FROM   shows 
                       INNER JOIN `show_rollups` 
                               ON 
                                `show_rollups`.`show_id` = `shows`.`id` 
                                    AND ( `show_rollups`.`device_id` = 3 ) 
                                    AND ( `show_rollups`.`package_group_id` = 2 ) 
                                    AND ( `show_rollups`.`videos_count` > 0 ) 
                                LEFT OUTER JOIN `show_texts` ON 
                                    `show_texts`.`show_id` = `shows`.`id` 
                                        AND 
                                    `show_texts`.`is_deleted` = 0 
                                       AND 
                                    `show_texts`.`language` = 'en' 
                                       AND 
                                    `show_texts`.`region` = 'US'
                                       AND
                                    shows.is_browseable = 1 
                                    AND 
                                    show_texts.show_id IS NOT NULL 
                                    AND ( 
                                        `show_rollups`.`episodes_count` > 0 
                                        OR `show_rollups`.`clips_count` > 0 
                                        OR `show_rollups`.`games_count` > 0 
                                        )   


     ) ) 
    GROUP  BY companies.id 
    ORDER  BY Sum(show_region_counts.view_count) DESC 
    LIMIT  30 offset 30; 

现在的问题是,当我在升级前在 MySQL 5.1.73 中运行此查询时,查询只需要大约 1.5 秒,但升级到 5.6.23 后,现在可能需要长达 1 分钟。

所以我在 5.1.73 中对这个查询做了一个解释,我看到了这个:

放大版:http://i.stack.imgur.com/c4ko0.jpg

当我在 5.6.23 做 EXPLAIN 时,我看到了这个:

放大版:http://i.stack.imgur.com/CgBtA.jpg

我可以看到,在这两种情况下,都对 show 表进行了全面扫描(类型 ALL),但是否还有其他我没有看到的东西导致了 5.6 的大幅减速?

谢谢 是

【问题讨论】:

  • 我看不懂那些解释计划 - 你会把它们粘贴为等宽文本吗?
  • 请在 http:bugs.mysql.com 写一个错误报告;他们想知道新优化器比旧优化器更差的情况。
  • 据我所知,第二个解释计划看起来比第一个更好
  • 另外,可以通过分析检索其他有用的信息:dev.mysql.com/doc/refman/5.0/en/show-profiles.html。这两台服务器上的硬件是否完全相同?
  • 对不起,图片看起来很小,但是如果您转到此处的直接网址,它们会更清晰:5.1:i.stack.imgur.com/c4ko0.jpg 5.6:i.stack.imgur.com/CgBtA.jpg

标签: mysql sql performance mysql-5.6 mysql-5.1


【解决方案1】:

请提供SHOW CREATE TABLE。没有那个,我猜你错过了这个理想的索引:

show_rollups: INDEX(device_id, package_group_id, videos_count)

你有LEFT OUTER JOIN show_texts ... ON ... show_texts.show_id IS NOT NULL。这可能是错误的,原因有两个:(a) 如果您不是在寻找 NULL,请不要使用 LEFT,以及 (b) NULL 测试应该在缺少的 @ 987654327@ 子句,不在ON 子句中。

摆脱IN ( SELECT ... ) 可能在两台机器上都有帮助:

SELECT  c.*
    FROM  
      ( SELECT  DISTINCT st.company_id AS id
            FROM  shows
            INNER JOIN  `show_rollups` AS sr ON sr.`show_id` = `shows`.`id`
              AND  ( sr.`device_id` = 3 )
              AND  ( sr.`package_group_id` = 2 )
              AND  ( sr.`videos_count` > 0 )
            LEFT OUTER JOIN  `show_texts` AS st ON st.`show_id` = `shows`.`id`
              AND  st.`is_deleted` = 0
              AND  st.`language` = 'en'
              AND  st.`region` = 'US'
              AND  shows.is_browseable = 1
              AND  st.show_id IS NOT NULL
              AND  ( sr.`episodes_count` > 0
                      OR  sr.`clips_count` > 0
                      OR  sr.`games_count` > 0 ) 
      ) AS x
    JOIN  `companies` AS c ON x.id = c.id
    LEFT OUTER JOIN  `company_texts` AS ct ON ct.`company_id` = c.`id`
          AND  ct.`language` = 'en'
          AND  ct.`region` = 'US'
    INNER JOIN  show_texts AS st ON st.company_id = c.id
          AND  st.`is_deleted` = 0
          AND  st.`language` = 'en'
          AND  st.`region` = 'US'
    INNER JOIN  show_region_counts AS src ON src.show_id = st.show_id
          AND  src.region = 'US'
    WHERE  ( c.`id` NOT IN ( '77', '26' ) )
      AND  ( ct.is_deleted = 0 )
    GROUP BY  c.id
    ORDER BY  Sum(src.view_count) DESC
    LIMIT  30 offset 30; 

JOIN 有可能会干扰Sum(src.view_count) 中的计算。

【讨论】:

  • 嗨瑞克,感谢您的回复。关于 SHOW CREATE TABLE,如果我在 show_rollups 上检查,show_idpackage_group_iddevice_id 这些列上有一个唯一索引,而不是 device_id、package_group_id 和 videos_count。 id列也有主键,没有其他索引
  • 感谢 Rick James,我对您的 SQL 做了一个小修正,它运行良好且快速!
【解决方案2】:

很抱歉,我无法辨认我显示屏上的 EXPLAIN 屏幕抓图。

如果没有这些,我想知道表的架构是否发生了变化,或者数据库引擎的架构是否发生了变化。特别是,company.id 似乎被用作主键。

【讨论】:

  • 很抱歉图片看起来很小,但是如果您转到此处的直接 URL,它们会更清晰:5.1:i.stack.imgur.com/c4ko0.jpg 5.6:i.stack.imgur。 com/CgBtA.jpg
猜你喜欢
  • 2021-11-13
  • 2011-09-20
  • 2018-12-22
  • 2016-11-24
  • 1970-01-01
  • 2013-09-27
  • 2018-03-28
  • 2012-09-16
  • 2013-12-30
相关资源
最近更新 更多