相同的 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)
中的计算。
我遇到了一个奇怪的问题,在我们将数据库从 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,我看到了这个:
当我在 5.6.23 中执行 EXPLAIN 时,我看到了这个:
我可以看到,在这两种情况下,都对节目进行了全面扫描(键入 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)
中的计算。