2016-09-26 57 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的時間戳。 –