给出的是名为“ user_posts”的mySQL表,其中包含以下相关字段:
在所有三个字段中建立索引
我运行缓慢的查询在这里,并且我还创建了 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花费了这么长时间吗?还是我需要进行任何更改以使查询运行更快?
答案 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
。
更新
对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);