相同的 MySQL 查询在 5.6 中的运行速度比在 5.1 中慢得多

Same MySQL query runs much slower in 5.6 than in 5.1

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

这是 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; 

现在的问题是,当我运行这个查询在MySQL5.1.73升级前,查询只需要1.5秒左右,但是升级到5.6.23后,它现在最多需要 1 分钟。

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

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

当我在 5.6.23 中执行 EXPLAIN 时,我看到了这个:

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

我可以看到,在这两种情况下,都对节目进行了全面扫描(键入 ALL)table,但是是否有其他我没有看到的东西导致 5.6 中的大幅减速?

谢谢 是

抱歉,我无法在我的显示器上辨认出 EXPLAIN 屏幕截图。

否则,我想知道表的架构是否发生了变化,或者数据库引擎是否发生了变化。特别是,companies.id 似乎被用作主键。

请提供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 测试应该在缺少的 WHERE 子句中,而不是在 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) 中的计算。