不知道为什么

fhity93d  于 2021-06-17  发布在  Mysql
关注(0)|答案(1)|浏览(454)

我附上两个explain语句的结果,用于一个旧查询和该查询的新版本。
你看到什么不合理或看起来不对劲的东西了吗?在我添加tm、tsa和tcd表之后,查询变得很慢(4.5秒)。

在将这三个表添加到查询之前,它的速度非常快(0.001秒)。下面是解释的样子

tm表有四列(tm\u id(pk)、owner\u id、manager\u id、status),tcd有三列(tm\u id、cd\u id、created\u date)。tm\u id和cd\u id构成一个复合主键,cd\u id上还有另一个索引。tsa有三列(tm\u id、smpa\u id、created\u date),其中tm\u id和smpa\u id是一个复合主键,smpa\u id有另一个索引。
这么慢的原因是什么?
旧查询:

SELECT upcm_id, COUNT( * ) 
FROM user_post_content_master AS upcm
JOIN content_deck AS cd ON cd.cd_id = upcm.cd_id
JOIN social_media_post_account AS smpa ON smpa.smpa_id = upcm.smpa_id
JOIN post_content_master AS pcm ON pcm.pcm_id = upcm.pcm_id
WHERE smpa.user_id =2196
AND upcm.upcm_post_date >=1545891957
AND upcm.upcm_status =1
AND upcm.upcm_post_date >=1546560000
AND upcm.upcm_post_date <=1546732799
GROUP BY upcm.upcm_id
ORDER BY upcm.upcm_post_date ASC

新建查询:

SELECT upcm_id, COUNT( * ) 
FROM user_post_content_master AS upcm
JOIN content_deck AS cd ON cd.cd_id = upcm.cd_id
JOIN social_media_post_account AS smpa ON smpa.smpa_id = upcm.smpa_id
JOIN post_content_master AS pcm ON pcm.pcm_id = upcm.pcm_id
JOIN team_content_deck AS tcd ON ( tcd.cd_id = upcm.cd_id ) 
JOIN team_social_account AS tsa ON tsa.smpa_id = upcm.smpa_id
JOIN team_members AS tm ON tm.team_member_id = tsa.team_member_id
AND tm.team_member_id = tcd.team_member_id
AND tm.owner_id =2196
AND tm.manager_id =2196
AND tm.status =1
WHERE smpa.user_id =2196
AND upcm.upcm_post_date >=1545891957
AND upcm.upcm_status =1
AND upcm.upcm_post_date >=1546560000
AND upcm.upcm_post_date <=1546732799
GROUP BY upcm.upcm_id
ORDER BY upcm.upcm_post_date ASC

如果我从tm表中删除条件,它又快了。不过,连接没有任何变化。

EXPLAIN SELECT upcm_id, COUNT( * ) 
FROM user_post_content_master AS upcm
JOIN content_deck AS cd ON cd.cd_id = upcm.cd_id
JOIN social_media_post_account AS smpa ON smpa.smpa_id = upcm.smpa_id
JOIN post_content_master AS pcm ON pcm.pcm_id = upcm.pcm_id
JOIN team_content_deck AS tcd ON ( tcd.cd_id = upcm.cd_id ) 
JOIN team_social_account AS tsa ON tsa.smpa_id = upcm.smpa_id
JOIN team_members AS tm ON tm.team_member_id = tsa.team_member_id
AND tm.team_member_id = tcd.team_member_id
WHERE smpa.user_id =2196
AND upcm.upcm_post_date >=1545891957
AND upcm.upcm_status =1
AND upcm.upcm_post_date >=1546560000
AND upcm.upcm_post_date <=1546732799
GROUP BY upcm.upcm_id
ORDER BY upcm.upcm_post_date ASC

3bygqnnd

3bygqnnd1#

我看到的区别很可能是因为键选择了upcm,旧查询选择了upcm\u post\u date,新查询选择了cd\u id。
由于数据不够,从名称上看,cd\u id的基数似乎比upcm\u post\u date要低得多。
更新(摘自我下面的评论):
一个可能的原因是由于mysql为查询决定的表序列,content\u deck位于user\u post\u content\u master之前。因为mysql使用嵌套循环算法进行连接,所以用户\u post\u content\u master位于连接的内部循环中。
当tm.owner\u id存在时,您会有一个持续的查找,这会导致mysql优化器决定它会战胜范围扫描。
在highperformancemysql一书中,有一章讨论了查询优化。有一种技术叫做:连接分解,即将一个大的连接查询分离为一个小的连接查询。另外一个好处是可以缓存一些公共数据。
我不确定index hint在这种情况下是否有帮助(只是提示或强制mysql为upcm使用post\u数据):选择*from user\u post\u content\u master use index(upcm\u post\u date)

相关问题