【发布时间】:2020-10-06 16:48:24
【问题描述】:
我有一个包含 1M 行(并且还在增长)的 MESSAGE 表。每个消息查询都涉及选择行 WHERE isRequest = True 或 WHERE isRequest = False,但绝不会同时选择两者。我的绝大多数查询都在寻找 isRequest = False。该表的写入非常频繁,我需要保持快速写入(因为用户喜欢以低延迟相互发送消息)。另请注意,MESSAGE 表目前除了主键之外没有任何列索引。
95% 的行有 isRequest = False,只有 5% 的行有 isRequest = True。 在这种情况下索引 isRequest 布尔字段是否更高效?
此外,我了解索引列会消耗内存,但是对于所有列数据类型,包括布尔值,这种开销等效吗?
更新:
在与@Rick James 进一步分析后,我们提出了一个新的表格方案(请注意,所有 PK 都是自动递增的,因此时间相对性是可辨别的):
MESSAGE (id=PK) (sender_id, recipient_id, conversation_id = FKs)
---------------------------------------------------------------
id sender_id recipient_id message conversation_id
1 1 2 "hows it going" 4
2 2 1 "great! hbu" 4
3 1 8 "hey man" 3
4 9 1 "please respond" 2
5 4 6 "goodnight girl" 1
CONVERSATION (id=PK) (userA_id, userB_id = FKs)
-----------------------------------------------
id userA_id userB_id
1 4 6
2 1 9
3 1 8
4 1 2
USERCONVERSATION (id=PK) (userA/B_id, conver_id, lastMsg_id = FKs)
------------------------------------------------------------------
id userA_id userB_id conver_id lastMsg_id isRequest
1 4 6 1 5 False
2 6 4 1 5 False
3 1 9 2 4 True
4 9 1 2 4 True
5 1 8 3 3 False
6 8 1 3 3 False
7 1 2 4 2 False
8 2 1 4 2 False
索引:
MESSAGE: index(id),
index(conversation_id, id)
CONVERSATION: index(id),
USERCONVERSATION: index(id),
index(user_id, isRequest),
index(user_id, lastMessage_id),
index(conversation_id)
应用中的查询:
由于如上所述的正确索引,以下查询应该是高性能的。如果可以改进,请与我们联系。
获取变量 userID 的最近 20 个对话(包括最后的消息内容和其他用户的信息):
SELECT T4.userB_id, T4.username, T4.profilePic, T4.conver_id,
T4.message
(
SELECT T1.userB_id, T2.username, T2.profilePic, T1.conversation_id,
T1.lastMessage_id
FROM
(
SELECT userB_id, conversation_id, lastMessage_id
FROM rage.userconversation
WHERE userA_id = {userID}
AND isRequest=False
) AS T1
LEFT JOIN rage.user AS T2 ON T1.userB_id = T2.id AS T3
)
LEFT JOIN rage.message AS T4 ON T1.lastMessage_id = T4.id
ORDER BY T4.id DESC
LIMIT 20
单词解释:获取最近的 USERCONVERSATION 行中的 20 行,因为 lastMessage 存储在那里。为了找到给定用户最近的 20 个,请选择 user_id = userID 的所有行并按 lastMessage_id DESC 排序。这是准确的,因为 message_id 是自动递增的。除了最后一条消息,我们还需要获取对话中其他用户的一些用户数据(个人资料图片、用户名)。我们通过左连接来实现这一点。
结果:
RESULT (for userID = 1)
---------------------------------------------------------------
userB_id username profilePic message conver_id
8 John 8.jpg "hey man" 3
2 Daisy 2.jpg "great! hbu" 4
然后当用户点击对话时,由于我们有对话 ID,我们只需:
SELECT * FROM rage.message WHERE conversation_id={conver_id} ORDER BY id DESC LIMIT 20
希望我们索引 (conversation_id, id) 后排序很快。
【问题讨论】:
-
我也有类似的情况,相信最好在这里索引一下。
-
你能解释一下吗?
-
通过教科书和网络和 SO,特别是通过 DBMS 手册,通过查询引擎了解关系和 SQL 优化/实现的基础知识——所有这些都立即导致索引、计划、统计和 SARGability。在您学习并应用这些基础知识后,要求重新优化。期望对问题进行适当的研究。请参阅 How to Ask、其他 help center 链接和投票箭头鼠标悬停文本。
-
请用文字描述您的示例试图做什么。也许它正在寻找它们之间的任一方向的消息?但是
LEFT JOIN在做什么呢? -
@Rage -
isRequest如何适合您的示例??
标签: mysql sql django django-models database-design