Is there a simpler way to achieve this style of user messaging?

前端 未结 13 1150
轮回少年
轮回少年 2020-12-24 12:20

I have created a messaging system for users, it allows them to send a message to another user. If it is the first time they have spoken then a new conversation is initiated,

13条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-24 13:11

    If you can only have one conversation between users, I don't see a reason for a dedicated conversations table. For this query to work fast, you would need a composite index on (user, message_id) which is impossible if these fields are in different tables. Move user_id and friend_id to the userconversations. This will make your table 8 bytes per record heavier (even assuming 8-byte identifiers) which is hardly a problem for a table containing text messages.

    If you have few conversations per user with many messages in each, use this:

    SELECT  um.*
    FROM    (
            (
            SELECT  MAX(id) AS messageId
            FROM    usermessages m1
            WHERE   user_id = :me
            GROUP BY
                    friend_id
            ORDER BY
                    messageId DESC
            LIMIT 10
            )
            UNION ALL
            (
            SELECT  MAX(id) AS messageId
            FROM    usermessages m1
            WHERE   frient_id = :me
            GROUP BY
                    user_id
            ORDER BY
                    messageId DESC
            LIMIT 10
            )
            ) q
    JOIN    usermessages um
    ON      um.id = q.messageId
    ORDER BY
            id DESC
    LIMIT 10
    

    Create separate indexes on user_id and friend_id

    If you have many conversations with few messages in each, use this query:

    (
    SELECT  *
    FROM    usermessages um
    WHERE   user_id = :me
            AND id = 
            (
            SELECT  MAX(id)
            FROM    usermessages umi
            WHERE   umi.user_id = um.user_id
                    AND umi.friend_id = um.friend_id
            )
    ORDER BY
            id DESC
    LIMIT 10
    )
    UNION ALL
    (
    SELECT  *
    FROM    usermessages um
    WHERE   frient_id = :me
            AND id = 
            (
            SELECT  MAX(id)
            FROM    usermessages umi
            WHERE   umi.user_id = um.user_id
                    AND umi.friend_id = um.friend_id
            )
    ORDER BY
            id DESC
    LIMIT 10
    )
    ORDER BY
            id DESC
    LIMIT 10
    

    The idea behind this query is that it just descends all messages for the given user, checking that each message is the last in its conversation. This may be much faster than sorting all last messages for all conversations (if you have many of them).

    For this to work fast, create indexes on

    friend_id
    user_id, friend_id
    

提交回复
热议问题