【发布时间】:2018-10-05 09:20:37
【问题描述】:
我正在设计一个用于聊天对话的表格。而不是创建 2 个表:对话和消息。我只设计了一张表:对话并使用JSONB 字段作为消息。
你们看看这张照片:
这个数据库结构解决方案是好是坏?如果它不好,我还有其他解决方案吗?
【问题讨论】:
标签: database postgresql database-design
我正在设计一个用于聊天对话的表格。而不是创建 2 个表:对话和消息。我只设计了一张表:对话并使用JSONB 字段作为消息。
你们看看这张照片:
这个数据库结构解决方案是好是坏?如果它不好,我还有其他解决方案吗?
【问题讨论】:
标签: database postgresql database-design
我强烈建议您规范化您的表结构。
参与者应进入包含id_conversation 和id_user 列的单独表格。搜索和更新比使用(json)数组更好。
与messages 相同。为什么不将它们存储到带有id_conversation、timestamp、id_user、message_text 列的单独表中?它也可以更好地用于搜索和更新。它使您的对话表变得更小。
另外:participants 列的用途是什么?如果您有每个对话的消息,您可以轻松地向表格询问所有向对话提交消息的用户,例如
SELECT DISTINCT id_user FROM messages WHERE id_conversation = 42
编辑:
原则上:100 万个数据集很多,但不是一张巨大的表。具有良好表设计的 Postgres 应该不会有任何问题。但我假设一个对话包含的消息要少得多,因此您可以在过滤和索引方面做很多事情。
1。 我强烈建议您为您的表格考虑一些巧妙的索引,这样可以使搜索变得非常快。也许消息时间戳上的索引可能会有所帮助,而转换 ID 上的索引可能会有所帮助:
CREATE INDEX idx_messages_timestamp
ON messages (timestamp);
CREATE INDEX idx_messages_conversations
ON messages (id_conversation);
如果您想获取较新的消息,使用 DESC 顺序 (... ON messages(... DESC)) 创建索引可能会有所帮助
2。 对于非常大的表(我的意思是非常大的表),partition 它可能会有所帮助。这会根据某个标准在内部拆分您的表格 - 可能是时间戳(例如每月或每年)。因此,如果您主要获取一些较新的数据,则较旧的数据将在内部存档在单独的表中。所以查询只针对所请求的较小表的行。
但这有点高级:https://www.postgresql.org/docs/current/static/ddl-partitioning.html
【讨论】:
participants。兄弟。如果规范化您的表结构(分为 2 个表:Message 和 Conversation),如果在 Pagination Process 中,我们肯定需要在每个请求中按会话 ID 过滤消息。如果消息表中的行太多,我认为它太慢了!
SELECT 10 FROM messages WHERE id_conversation = 42对于每个Pagination Request,它比我们SELECT FROM conversation WHERE id = 42慢并得到Message Column
SELECT 10 ...是什么意思