2013-11-01 97 views
6

我的網站有一個關注者/關注系統(如Twitter的)。我的困境是創建數據庫結構來處理誰跟蹤誰。關注者/關注數據庫結構

我想出什麼樣的主意是創建一個表是這樣的:

id | user_id | followers | following 
    1 | 20  | 23,58,84 | 11,156,27 
    2 | 21  | 72,35,14 | 6,98,44,12 
... | ...  | ...  |  ... 

基本上,我在想,每個用戶將不得不爲他們的追隨者,他們正在關注的用戶列一行。追隨者和他們所關注的人將用逗號分隔其用戶標識。

這是把它處理的有效途徑?如果不是,最好的選擇是什麼?

謝謝。

回答

19

這是最糟糕的做法。這是反對正常化。有2個獨立的桌子。用戶和User_Followers。用戶將存儲用戶信息。 User_Followers將是這樣的:

id | user_id | follower_id 
1 | 20  | 45 
2 | 20  | 53 
3 | 32  | 20 

USER_ID和Follower_Id的將是外鍵指在用戶表中的ID列。該表示的

+0

是的,這是我想到的第二個結構,但認爲這並不是傳統的做法。謝謝。 – Burrows

+2

我認爲*正常化*是過去的事情。您可能爲* Oracle *工作。 – Vad

+1

@Vad我確定不適用於Oracle :)規範化是關係數據庫系統和數據的概念,只要這些系統存在,它就不會成爲過去的東西:) – regulus

4

一個缺點是每個關係被編碼兩次:一次是在排爲從動件和行以下用戶一旦在,使其難以保持數據的完整性和更新乏味。

我會做出一個用戶表和關係一個表。關係表如下所示:

id | follower | following 
1 | 23  | 20 
2 | 58  | 20 
3 | 84  | 20 
4 | 20  | 11 
... 

這種添加新關係的方式只是插入,刪除關係就是刪除。計算數量以確定給定用戶有多少個追隨者也更容易。

1

不,你描述的方法有幾個問題。

首先,存儲多個數據點作爲逗號分隔的字符串具有許多問題。很難加入(儘管您可以使用like加入會降低性能),而且難以搜索,並且無法按照您希望的方式進行索引。其次,如果你同時存儲一個追隨者列表和一個追隨者列表,你有冗餘數據(A跟隨B的事實將顯示在兩個地方),這既浪費空間,也浪費空間也會造成數據失去同步的可能性(如果數據庫顯示A在B的追隨者列表中,但在A的追隨者列表中未顯示B,則數據不一致以難以從中恢復)。

相反,使用連接表。這是一個單獨的表格,每行都有一個用戶標識和一個關注者標識。這允許將事物存儲在一個位置,允許建立索引和連接,還允許您向該行添加更多列,例如顯示下列關係何時開始。

2

沒有比迄今爲止提出的其他答案更好物理結構:

CREATE TABLE follower (
    user_id INT, -- References user. 
    follower_id INT, -- References user. 
    PRIMARY KEY (user_id, follower_id), 
    UNIQUE INDEX (follower_id, user_id) 
); 

InnoDB表是clustered,所以二級索引行爲不同於在基於堆的表,而且可以有意想不到的開銷,如果你沒有意識到這一點。代理主鍵id只是增加了另一個沒有很好理由的索引,並且使得{user_id,follower_id}和{follower_id,user_id}上的索引比他們需要的更胖(因爲集羣表中的輔助索引隱式地包含副本的PK)。

上表中沒有surrogate keyid並且(假設InnoDB)在物理上由兩個B樹(一個用於主/集羣鍵,一個用於二級索引)表示,其大致與用於搜索的效率在兩個方向。如果你只需要一個方向,你可以放棄二級索引,然後下一個B樹。

順便說一句,你所做的是違反了atomicity,因此1NF的原則。


和每一個附加的索引需要的空間,降低了高速緩存效率和影響插入/更新/刪除的性能。

從followee到follower,反之亦然。