如何优化此查询以更快地执行?

时间:2009-07-23 22:36:38

标签: mysql

这适用于我网站上的朋友模块,用户可以在这里与朋友交朋友。 这些存储在“friends:”表中,发起友谊的人是friendship_inviter,而批准/拒绝结束的人是friendhsip_accepter

SELECT user_id, user_name, user_gender
FROM friends
LEFT JOIN users
    ON (   users.user_id = friends.friendship_inviter 
        OR users.user_id = friends.friendship_accepter)
WHERE (friendship_inviter = '125' OR friendship_accepter = '125') 
AND    user_id !='125' 
AND    friendship_level = 1;

这会进行全表扫描,即使表格不大(15,000个用户,3000个友谊),平均需要1-1.5秒。

如何以对服务器不那么重要的方式输出当前朋友列表?

5 个答案:

答案 0 :(得分:4)

SELECT user_id, user_name, user_gender
FROM friends
LEFT JOIN users
    ON users.user_id = friends.friendship_accepter
WHERE  friendship_accepter = '125' 
AND    user_id !='125' 
AND    friendship_level = 1
UNION 
SELECT user_id, user_name, user_gender
FROM friends
LEFT JOIN users
    ON users.user_id = friends.friendship_inviter
WHERE friendship_inviter = '125'  
AND    user_id !='125' 
AND    friendship_level = 1;

当然,看起来你没有从“friends”表中选择任何东西,并且你的WHERE子句中有额外的列,所以我实际上会编写INNER JOIN,这相当于LEFT JOIN中的你发布的案例:

SELECT user_id, user_name, user_gender
FROM friends
INNER JOIN users
    ON users.user_id = friends.friendship_accepter
WHERE  friendship_accepter = '125' 
AND    user_id !='125' 
AND    friendship_level = 1
UNION 
SELECT user_id, user_name, user_gender
FROM friends
INNER JOIN users
    ON users.user_id = friends.friendship_inviter
WHERE friendship_inviter = '125'  
AND    user_id !='125' 
AND    friendship_level = 1;

答案 1 :(得分:1)

将索引添加到WHERE子句和JOIN中使用的列/组合。

答案 2 :(得分:1)

部分问题可能是friendship_level基数较低。有时,在低基数列上,查询优化器仍会决定进行表扫描。

在查询中考虑friendship_level条件之前,执行EXPLAIN,并确保其他条件正在执行FIRST。在满足前两个条件后剩余的记录扫描将花费更少的时间。

答案 3 :(得分:0)

确保您已将user_id, friendship_accepter, friendship_inviter and friendship_level编入索引。

那时候你只发布原始查询时间还是包含输出结果的时间?如果它还包括输出,则它可能不是查询,而是输出。

另一件可能会减慢结果的事情是,如果它是在一个缓慢的网络(即互联网)上。缓慢的时间可能是因为这个而不是因为查询。

答案 4 :(得分:0)

我在我的社交网站上做了一些非常相似的事情,但我的情况有点不同, 我为每个友谊插入2条记录,这允许我向用户显示;

待定的朋友请求 发送好友请求 和确认的朋友

我也没有考虑使用UNION。我目前在好友表中有大约50,000个用户和超过1百万行,这对我来说非常有用