我有查询:
EXPLAIN SELECT talks.*, users.*
FROM (
SELECT p_talk
FROM posts WHERE p_user=1
GROUP BY p_talk
ORDER BY MAX(p_time) DESC
LIMIT 30
) AS posts
JOIN talks
ON p_talk=t_id
JOIN users
ON t_user=u_id
我制作了一个索引“历史”:
p_user, p_time, p_talk
但我仍然得到以下EXPLAIN输出:
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 30
1 PRIMARY talks eq_ref PRIMARY,t_user PRIMARY 4 posts.p_talk 1
1 PRIMARY users eq_ref PRIMARY PRIMARY 4 channels.talks.t_user 1
2 DERIVED posts ref p_user,history history 4 39320 Using where; Using index; Using temporary; Using f...
为什么它会查看与p_user匹配的每个帖子?
修改 如果我删除GROUP和ORDER,它仍会显示EXPLAIN输出中的所有39320行。这让我很困惑。为什么它会估计它将遍历所有匹配p_user = 1的行,如果我告诉它返回前30个?
答案 0 :(得分:0)
在大多数数据库中,此表的最佳索引为:
p_user, p_talk, p_time
在group by
之前评估order by
,因此该列必须首先在索引中。
我并非100%确定MySQL会利用此索引进行此查询。
编辑:
如果您确信在最近的500条记录中有足够的p_talk
值,那么您可以将以下内容与现有索引一起使用:
FROM (SELECT p_talk
FROM (SELECT p_talk, p_time
FROM posts
WHERE p_user = 1
ORDER BY p_time DESC
LIMIT 500
) p
GROUP BY p_talk
ORDER BY MAX(p_time) DESC
LIMIT 30
) AS posts