查询运行太慢

时间:2019-09-23 09:00:41

标签: mysql sql

给出的是名为“ user_posts”的mySQL表,其中包含以下相关字段:

  • user_id
  • user_status
  • influencer_status

在所有三个字段中建立索引

我运行缓慢的查询在这里,并且我还创建了 dbFiddle 。解释输出在 dbfiddle 中:

SELECT 
   P.user_post_id,     
   P.user_id_fk,P.post_type,
   P.who_can_see_post,
   P.post_image_id,P.post_video_id, 
   U.user_name, U.user_fullname,U.influencer_status 
 FROM user_posts P FORCE INDEX (ix_user_posts_post_id_post_type)
   INNER JOIN users U FORCE INDEX (ix_status_istatus)
   ON P.user_id_fk = U.user_id 
 WHERE 
   U.user_status='1' AND 
   U.influencer_status = '1' AND 
   (P.who_can_see_post IN('everyone','influencer','friends')) AND 
   (P.post_type IN('image','video'))
   AND p.user_post_id > 30
 ORDER BY 
    P.user_post_id 
 DESC LIMIT 30

查询耗时极长,大约需要6-15秒。否则数据库不会很忙,并且在其他查询上表现良好。

我显然想知道为什么查询这么慢。

有没有一种方法可以准确地弄清mySQL花费了这么长时间吗?还是我需要进行任何更改以使查询运行更快?

2 个答案:

答案 0 :(得分:5)

ix_status_istatus键的定义阻止了它被用来优化WHERE子句,因为它包含user_id子句中未使用的WHERE。将索引重新定义为

ALTER TABLE `users`
  ADD PRIMARY KEY (`user_id`),
  ADD KEY ix_status_istatus (user_status, influencer_status);

允许使用它,并应加快查询速度,将users上的搜索更改为使用index而不是temporary and filesort

Demo on dbfiddle

更新

对dbfiddle的进一步分析表明,最好不要从FORCE INDEX表中删除P,因为这是不必要的(仅需要PRIMARY键)并更改{ {1}}到STRAIGHT_JOIN,即将JOIN写为:

JOIN

答案 1 :(得分:1)

我认为您应该使用ON语句中的条件限制连接零件的结果集。

这就像在联接过程中进行过滤,而不是先联接然后进行过滤。

我检查了查询计划,该计划显示了索引的全部使用情况。

SELECT 
   P.user_post_id,     
   P.user_id_fk,P.post_type,
   P.who_can_see_post,
   P.post_image_id,
   P.post_video_id, 
   U.user_name, 
   U.user_fullname,
   U.influencer_status 

 FROM user_posts P

 INNER JOIN 
   users U 
       FORCE INDEX (
         users_user_status_index, 
         users_influencer_status_index
       )
   ON 
     U.user_id = P.user_id_fk AND 
     U.user_status='1' AND 
     U.influencer_status='1'

 WHERE 
   P.who_can_see_post IN('everyone','influencer','friends') AND 
   P.post_type IN('image','video') AND 
   P.user_post_id > 30

 ORDER BY 
    P.user_post_id DESC

 LIMIT 30

我创建的索引:

ALTER TABLE `users`
  ADD PRIMARY KEY (`user_id`),
  ADD KEY users_user_status_index(user_status),
  ADD KEY users_influencer_status_index(influencer_status);

dbfiddle