2016-09-26 62 views
1

背景

我正在为自定义Web应用程序构建一个简单的聊天客户端。我需要存储所有聊天记录。用户也可以向个人或群组发送消息。认为谷歌聊天(我告诉我的客户使用,而不是他坚持自定义)。我的数据库的构建方式:如何优化聊天室查询?

表:聊天室
int主键ChatRoomID
VARCHAR(64)名称

ChatMessage
int主键ChatMessageID
int 用户ID
INT ChatRoomID
VARCHAR(2000)消息
日期时间日期

ChatUser
INT ChatRoomID
INT 用户ID
INT LastMessageID 主键(ChatRoomID,用户名)

我使用SQL服务器等解决方案需要在两个平台上工作,将尽快迁移到MySQL。

我的问题

假设一个用户刚刚登录我需要拉的所有聊天室与优秀的邮件列表。我当前的查询看起来是这样的:

 SELECT DISTINCT 
     cr.ChatRoomID AS id, 
     cu.LastMessageID AS label 
     FROM ChatRooms cr 
     LEFT JOIN ChatUsers cu ON cu.ChatRoomID = cr.ChatRoomID 
     LEFT JOIN ChatMessages cm ON cm.ChatRoomID = cr.ChatRoomID 
     WHERE cu.UserID = :user_id 
     AND cu.LastMessageID < cm.ChatMessageID 

问题

这似乎是工作相当出色。不过,我怀疑当他们有几十个用户,数千个房间和数百万条消息时,这会变得效率低下。如何优化此查询(或数据库结构)以使此请求(具有针对给定用户的未解决消息的聊天室的数量)成为性能可伸缩的查询?

我主要关心的是我不得不为这个查询使用“distinct”标志。所以这可能会加入一个临时表的数百万,然后过滤到2个数字。

实施例数据

用户
1 | A医生
2 | B医生
3 | Biller A
4 | Biller B
5 |老板

ChatRoom
1 | Doctor Group
2 |账单组

ChatUser
客房|用户|消息
- | - | -------
1 | 1 | 0
1 | 2 | 2
1 | 5 | 2
2 | 3 | 6
2 | 4 | 0
2 | 5 | 5

聊天消息
ID |房间|用户|消息
- | - | - | -------
1 | 1 | 5 | “今天每个人怎么样?”
2 | 1 | 2 | “我很好,在5号房间需要更多的乐队帮助。”
3 | 2 | 5 | “有人可以用Band Aids补充房间5吗?”
4 | 2 | 3 | “这不是我的工作得到一个走狗。”
5 | 2 | 5 | “无论如何,或者你被解雇了。”
6 | 2 | 3 | “这不是你,我放弃了。”

在这种情况下用户1和4是上班迟到了,当他们登录的消息会弹出,以及用户5是在他的计费部门下一次的惊喜我运行查询。

+0

你能提供一些测试数据给我们测试和理解可扩展性方面 – TheGameiswar

+0

和实际ddl包括索引。 –

+0

我不知道ddl是什么,索引应该非常明显。我确实添加了一个示例场景。 – danielson317

回答

4

您可以优化该查询是这样的:

select cr.ChatRoomID AS id, 
    cu.LastMessageID AS label 
from ChatUsers cu inner join ChatRooms cr ON cu.ChatRoomID = cr.ChatRoomID 
where cu.UserID = :user_id and 
exists (select 1 from ChatMessages cm where cm.ChatRoomID = cr.ChatRoomID and cu.LastMessageID < cm.ChatMessageID); 

主要有2个问题与当前查询:

  1. 左侧的接合部也将带来空白记录。此外,您将通过使用不同的处理方式处理多个记录。
  2. 记录列表再次连接到所有消息表数据,因此如果消息表包含更多数据,那么您的查询注定会变慢。

这是类似的东西,我们在https://www.applozic.com解决。

声明:我在Applozic工作。

+0

这似乎消除了作为消息表的大量连接。但是,对于包装查询的每个结果,不会执行子查询吗?我觉得这可能会造成类似的问题。 – danielson317

+1

这样,每当第一条记录被提取时,查询就会停止并为另一条记录运行。另一种优化方法是在发布新消息时将消息时间戳保存在ChatUser表中,并根据保存的时间戳检查LastMessageId的时间戳。 –