知乎的私信系統資料庫是怎麼設計的?

顯示私信頁面的時候,只顯示跟每個人通信的最後一條,以及已經通了多少次私信。而顯示這個,應該不需要經過複雜的資料庫查詢吧。


知乎如何設計的我不知道,我倒是願意分享下我的網站(http://guiji.us)的私信設計。

這個問題我曾經也考慮過一段時間,為了效率,我覺得可以拆分為2個表

(表1) Id, F1, F2, ThreadID, Unread, Count

分別代表主鍵、F1,F2為私信發送或接收方的用戶ID,順序可以顛倒,不過有一個限制是F1& ThreadID 是私信內容表的一個外鍵,Unread 標記是否已讀。

(表2)Id, ThreadId, fromF1toF2, MessageBody, CreateTime

fromF1toF2 解釋下,就是標記是從F1發到F2,還是F2發到F1。

因為對於表1來說,不管是你發別人還是別人發你,你在私信裡面都能看到,他們沒有分開處理。

其他欄位看名字就知道什麼意思了吧。

然後,相關用例的實現:

(1)訪問「私信」頁面的時候,只用查詢到第一個表和第二個表的TOP1。

(SELECT ThreadID FROM Table1 WHERE F1 = ?) UNION ALL

(SELECT ThreadID FROM Table1 WHERE F2 = ?)

問號代表當前用戶的ID。

然後得到一個 ThreadID 的列表,在 Table2 中查詢該 ThreadID 對應的 TOP 1 記錄。

(2)發一條新私信

查詢表1是否有 (F1,F2) 的記錄。讓F1& 如果有的話,在表2創建一條新的記錄,ThreadID 保持不變。

如果沒有的話,表1和表2同時創建,對應一個新的ThreadID。

其中,需要特別注意要索引的地方:F1,F2 建立聯合索引,和F2的單獨索引。

還有一個方案,就是表1引入冗餘。這樣上述的用例1就可以只查詢一個表了。記錄下 MessageBody, CreateTime。在表2引入Trigger,當有最新記錄變動時候,UPDATE表1。


單就你的問題描述來看,很多KV存儲都可解決。


推薦閱讀:

WordPress 與 MySQL 資料庫之間是什麼關係?哪些數據存在資料庫里?以什麼形式存儲的?
網站間隙性502是怎麼回事?怎麼解決?
如何評價微軟發布了SQLServer on Linux?
用Google搜索什麼會用時大於1秒?
硬碟寫到一半斷電時文件系統發生了什麼?

TAG:知乎 | 資料庫 | 知乎設計 |