【发布时间】:2016-09-26 15:13:13
【问题描述】:
背景
我正在为自定义 Web 应用程序构建一个简单的聊天客户端。我需要存储所有聊天记录。用户还可以向个人或群组发送消息。想想谷歌聊天(我告诉我的客户改用它,但他坚持自定义)。我的数据库结构如下:
表格:聊天室
int 主键 ChatRoomID
varchar(64) 名称表格ChatMessage
int 主键 ChatMessageID
int 用户 ID
int ChatRoomID
varchar(2000) 消息
日期时间 日期表格 ChatUser
int ChatRoomID
int 用户 ID
int LastMessageID 主键(ChatRoomID、UserID)
我正在使用 SQL Server,并且将很快迁移到 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 |比勒 A
4 |比勒 B
5 |老板聊天室
1 |博士集团
2 |计费组聊天用户
房间 |用户 |留言
- | - | --------
1 | 1 | 0
1 | 2 | 2
1 | 5 | 2
2 | 3 | 6
2 | 4 | 0
2 | 5 | 5聊天消息
身份证 |房间 |用户 |留言
- | - | - | --------
1 | 1 | 5 | “今天大家好吗?”
2 | 1 | 2 | “我很好。5 号房间需要更多创可贴。”
3 | 2 | 5 | “有人可以用创可贴补给 5 号房间吗?”
4 | 2 | 3 | “找个走狗不是我的工作。”
5 | 2 | 5 | “无论如何都要这样做,否则你就被解雇了。”
6 | 2 | 3 | “这是你的不是你的,我退出了。”
在这种情况下,用户 1 和 4 上班迟到,当他们登录时会弹出一条消息,下次我运行查询时,用户 5 会在他的计费部门遇到惊喜。
【问题讨论】:
-
您能否提供一些测试数据供我们测试和了解可扩展性方面
-
还有实际的 ddl 包括索引。
-
我不知道ddl是什么,索引应该很明显。我确实添加了一个示例场景。
-
ddl = 数据定义语言(创建表的脚本)。仅仅因为索引应该是显而易见的并不意味着您已经正确定义了它们。索引是优化中非常关键的部分。
-
我不需要关于索引的帮助 我需要帮助编写一个好的查询假设索引与它们显示的完全一样(房间 == 房间、消息 == 消息等)。另一种表结构也是可以接受的。
标签: sql sql-server database-design