不要抓住重复项(MYSQL DISTINCT GROUP BY)

时间:2014-10-27 07:20:43

标签: mysql sql group-by distinct

我有一个基于会话的消息系统。 (被视为论坛帖子的消息。类似于gmail。) 表:

convos (PRIMARY cid)
messages (PRIMARY mid)
users (PRIMARY uid)

convos中的每一行都是一个帖子。消息中的每一行都是一个回复,包括它所属的cid。我通过使用该cid抓取x最近的消息来加载对话。我还将用户表加入消息ON uid。 (每条消息都有发件人的uid。)从users我得到user_name, avatar。为了说明,基本查询将如下所示:

SELECT
messages.body,
users.avatar
FROM messages
JOIN users ON (users.uid=messages.uid)
WHERE messages.cid=1

如果同一个用户做了很多回复,我会多次抓住她的头像,这是VARCHAR(头像图片的链接)。为了提高性能,我想只抓取每个avatar一次。我正在考虑使用GROUP BYDISTINCT

的子查询

更新

我要和罗比C的想法一起去。我有公开聊天,任何用户都可以回复并且回复增长。我将在每页显示20条回复。为了获得这20个回复所需的头像,我这样做:

    SELECT
    u.avatar
    FROM( 
        SELECT uid,cid 
        FROM messages  
        WHERE cid=1234
        ORDER BY date DESC LIMIT 20
    ) AS m
    JOIN users AS u ON (u.uid=m.uid)
    GROUP BY u.uid  

子查询最近的20个回复,使用JOIN获取用户数据,然后GROUP BY users.uid剪切重复项。似乎运作良好。

2 个答案:

答案 0 :(得分:2)

我认为您正在考虑的子查询不会提高性能。使用uid获取两个结果集并在代码中匹配它们可能会更容易,更高效。

获取邮件内容的查询:

SELECT
    messages.body, messages.uid
FROM messages
WHERE messages.cid=1;

获取头像的查询:

SELECT DISTINCT
    users.uid, users.avatar
FROM messages
JOIN users ON (users.uid = messages.uid)
WHERE messages.cid=1;

就查询执行时间而言,与您最初的单个查询相比,我认为您不会看到改进。但是,您可以减少IO和/或网络使用。

如果您发现自己经常收到相同的用户信息,那么考虑将整个用户表缓存在内存中是值得的。

答案 1 :(得分:0)

我认为您可能需要更改工作流程中的内容:

不要将您的头像直接存储在db中,而只存储头像文件的路径。通过这种方式,您不会每次都抓住头像,而只会抓住文件的路径。