MySQL解释基于条件值的计划更改
今天,我们注意到两个显然相同的查询导致了截然不同的执行计划,从而导致了截然不同的性能。 另一个令人吃惊的事实是,聚合超过50k+行的查询比聚合超过600个结果的查询运行速度快30倍。 “快速”查询运行约400ms,“慢速”查询运行约10sc 慢速查询:MySQL解释基于条件值的计划更改,mysql,Mysql,今天,我们注意到两个显然相同的查询导致了截然不同的执行计划,从而导致了截然不同的性能。 另一个令人吃惊的事实是,聚合超过50k+行的查询比聚合超过600个结果的查询运行速度快30倍。 “快速”查询运行约400ms,“慢速”查询运行约10sc 慢速查询: SELECT account_ownership_id, count(*) FROM posts JOIN accounts ON posts.account_id = accounts.id JOIN platforms ON accounts
SELECT account_ownership_id, count(*)
FROM posts
JOIN accounts ON posts.account_id = accounts.id
JOIN platforms ON accounts.platform_id = platforms.id
JOIN sponsor_annotations ON sponsor_annotations.post_id = posts.id
JOIN rightsholders_placements
ON (rightsholders_placements.rightsholder_id = sponsor_annotations.rightsholder_id
AND rightsholders_placements.placement_id = sponsor_annotations.placement_id)
JOIN clients_sponsors_placements
ON (clients_sponsors_placements.rightsholder_id = sponsor_annotations.rightsholder_id
AND clients_sponsors_placements.sponsor_id = sponsor_annotations.sponsor_id
AND clients_sponsors_placements.placement_id = sponsor_annotations.placement_id)
WHERE clients_sponsors_placements.client_id = 1125 and accounts.platform_id = 5
GROUP BY sponsor_annotations.account_ownership_id LIMIT 1000
+---+--------+-----------------------------+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+----+--------------------------------------------------------------------------------------------------------------------------------+-----+-------+----------------------------------------------+
| 1 | SIMPLE | platforms | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.0 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | accounts | ref | PRIMARY,fk_accounts_platforms | fk_accounts_platforms | 4 | const | 354 | 100.0 | Using index |
| 1 | SIMPLE | posts | ref | PRIMARY,fk_posts_accounts_id | fk_posts_accounts_id | 4 | sports.accounts.id | 2 | 100.0 | Using index |
| 1 | SIMPLE | sponsor_annotations | ref | sponsor_annotations,fk_sponsor_annotations_sponsor_placements,fk_sponsor_annotations_rightsholder_placements,fk_sponsor_annotations_sponsors,fk_sponsor_annotations_account_ownership_types | sponsor_annotations | 4 | sports.posts.id | 29 | 100.0 | |
| 1 | SIMPLE | clients_sponsors_placements | eq_ref | PRIMARY,fk_client_sponsor_placements_clients_rightsholders_sponsors,fk_client_sponsor_placements_sponsor_placements | PRIMARY | 16 | const,sports.sponsor_annotations.placement_id,sports.sponsor_annotations.rightsholder_id,sports.sponsor_annotations.sponsor_id | 1 | 100.0 | Using index |
| 1 | SIMPLE | rightsholders_placements | eq_ref | PRIMARY,fk_rightsholders_placements_rightsholders | PRIMARY | 8 | sports.sponsor_annotations.placement_id,sports.sponsor_annotations.rightsholder_id | 1 | 100.0 | Using index |
+---+--------+-----------------------------+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+----+--------------------------------------------------------------------------------------------------------------------------------+-----+-------+----------------------------------------------+
快速查询:
SELECT account_ownership_id, count(*)
FROM posts
JOIN accounts ON posts.account_id = accounts.id
JOIN platforms ON accounts.platform_id = platforms.id
JOIN sponsor_annotations ON sponsor_annotations.post_id = posts.id
JOIN rightsholders_placements
ON (rightsholders_placements.rightsholder_id = sponsor_annotations.rightsholder_id
AND rightsholders_placements.placement_id = sponsor_annotations.placement_id)
JOIN clients_sponsors_placements
ON (clients_sponsors_placements.rightsholder_id = sponsor_annotations.rightsholder_id
AND clients_sponsors_placements.sponsor_id = sponsor_annotations.sponsor_id
AND clients_sponsors_placements.placement_id = sponsor_annotations.placement_id)
WHERE clients_sponsors_placements.client_id = 1125 and accounts.platform_id = 1
GROUP BY sponsor_annotations.account_ownership_id LIMIT 1000
如您所见,这两个查询之间的唯一区别在于平台id where子句。我希望查询计划非常相似,但事实并非如此。而且,即使缓慢的查询聚集在更少的行上,也要花费更多的时间
同样有趣的是,将条件更改为“accounts.platform_id in(1,5)”可以显著加快查询速度(查询速度与我们执行accounts.platform_id=1的查询速度一样快)
以下是慢速查询的解释计划:
SELECT account_ownership_id, count(*)
FROM posts
JOIN accounts ON posts.account_id = accounts.id
JOIN platforms ON accounts.platform_id = platforms.id
JOIN sponsor_annotations ON sponsor_annotations.post_id = posts.id
JOIN rightsholders_placements
ON (rightsholders_placements.rightsholder_id = sponsor_annotations.rightsholder_id
AND rightsholders_placements.placement_id = sponsor_annotations.placement_id)
JOIN clients_sponsors_placements
ON (clients_sponsors_placements.rightsholder_id = sponsor_annotations.rightsholder_id
AND clients_sponsors_placements.sponsor_id = sponsor_annotations.sponsor_id
AND clients_sponsors_placements.placement_id = sponsor_annotations.placement_id)
WHERE clients_sponsors_placements.client_id = 1125 and accounts.platform_id = 5
GROUP BY sponsor_annotations.account_ownership_id LIMIT 1000
+---+--------+-----------------------------+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+----+--------------------------------------------------------------------------------------------------------------------------------+-----+-------+----------------------------------------------+
| 1 | SIMPLE | platforms | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.0 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | accounts | ref | PRIMARY,fk_accounts_platforms | fk_accounts_platforms | 4 | const | 354 | 100.0 | Using index |
| 1 | SIMPLE | posts | ref | PRIMARY,fk_posts_accounts_id | fk_posts_accounts_id | 4 | sports.accounts.id | 2 | 100.0 | Using index |
| 1 | SIMPLE | sponsor_annotations | ref | sponsor_annotations,fk_sponsor_annotations_sponsor_placements,fk_sponsor_annotations_rightsholder_placements,fk_sponsor_annotations_sponsors,fk_sponsor_annotations_account_ownership_types | sponsor_annotations | 4 | sports.posts.id | 29 | 100.0 | |
| 1 | SIMPLE | clients_sponsors_placements | eq_ref | PRIMARY,fk_client_sponsor_placements_clients_rightsholders_sponsors,fk_client_sponsor_placements_sponsor_placements | PRIMARY | 16 | const,sports.sponsor_annotations.placement_id,sports.sponsor_annotations.rightsholder_id,sports.sponsor_annotations.sponsor_id | 1 | 100.0 | Using index |
| 1 | SIMPLE | rightsholders_placements | eq_ref | PRIMARY,fk_rightsholders_placements_rightsholders | PRIMARY | 8 | sports.sponsor_annotations.placement_id,sports.sponsor_annotations.rightsholder_id | 1 | 100.0 | Using index |
+---+--------+-----------------------------+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+----+--------------------------------------------------------------------------------------------------------------------------------+-----+-------+----------------------------------------------+
以及更快查询的解释计划:
+---+--------+-----------------------------+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------+----+--------------------------------------------------------------------------------------------------------------------------------------------------+-----+-------+----------------------------------------------+
| 1 | SIMPLE | platforms | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.0 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | clients_sponsors_placements | ref | PRIMARY,fk_client_sponsor_placements_clients_rightsholders_sponsors,fk_client_sponsor_placements_sponsor_placements | PRIMARY | 4 | const | 223 | 100.0 | Using index |
| 1 | SIMPLE | rightsholders_placements | eq_ref | PRIMARY,fk_rightsholders_placements_rightsholders | PRIMARY | 8 | sports.clients_sponsors_placements.placement_id,sports.clients_sponsors_placements.rightsholder_id | 1 | 100.0 | Using index |
| 1 | SIMPLE | sponsor_annotations | ref | sponsor_annotations,fk_sponsor_annotations_sponsor_placements,fk_sponsor_annotations_rightsholder_placements,fk_sponsor_annotations_sponsors,fk_sponsor_annotations_account_ownership_types | fk_sponsor_annotations_sponsor_placements | 12 | sports.clients_sponsors_placements.rightsholder_id,sports.clients_sponsors_placements.sponsor_id,sports.clients_sponsors_placements.placement_id | 158 | 100.0 | |
| 1 | SIMPLE | posts | eq_ref | PRIMARY,fk_posts_accounts_id | PRIMARY | 4 | sports.sponsor_annotations.post_id | 1 | 100.0 | |
| 1 | SIMPLE | accounts | eq_ref | PRIMARY,fk_accounts_platforms | PRIMARY | 4 | sports.posts.account_id | 1 | 100.0 | Using where |
+---+--------+-----------------------------+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------+----+--------------------------------------------------------------------------------------------------------------------------------------------------+-----+-------+----------------------------------------------+
如何更改查询或模式以确保在这两种情况下执行计划相同
谢谢,可能会运行?如果取消
限制,您的快速查询是否会更快?根据有限的查询判断执行计划可能会产生误导。另外,您能否添加绝对执行时间(例如,它更像是1s对30s还是1ms对30ms?@Solarflare:我尝试取消限制,但没有改变执行时间。绝对执行时间为400ms vs 10秒。将其添加到我的原始消息中。@GhostGambler我对该查询涉及的所有表运行了ANALYZE TABLE,但它没有帮助。可能运行?如果删除限制,您的快速查询是否会更快?根据有限的查询判断执行计划可能会产生误导。另外,您能否添加绝对执行时间(例如,它更像是1s对30s还是1ms对30ms?@Solarflare:我尝试取消限制,但没有改变执行时间。绝对执行时间为400ms vs 10秒。将其添加到我的原始消息中。@GhostGambler我在该查询涉及的所有表上运行了ANALYZE TABLE,但没有任何帮助。