2015-08-16 38 views
0

我的表架構爲:
A)卡桑德拉 - 二級索引和查詢性能

CREATE TABLE friend_list (
    userId uuid, 
    friendId uuid, 
    accepted boolean, 
    ts_accepted timestamp, 
    PRIMARY KEY ((userId ,accepted), ts_accepted) 
    ) with clustering order by (ts_accepted desc); 

在這裏,我能像執行查詢:

1. SELECT * FROM friend_list WHERE userId="---" AND accepted=true; 
2. SELECT * FROM friend_list WHERE userId="---" AND accepted=false; 
3. SELECT * FROM friend_list WHERE userId="---" AND accepted IN (true,false); 

但第三查詢涉及更多閱讀,所以我試圖改變這樣的架構:

B)

CREATE TABLE friend_list (
     userId uuid, 
     friendId uuid, 
     accepted boolean, 
     ts_accepted timestamp, 
     PRIMARY KEY (userId , ts_accepted) 
     ) with clustering order by (ts_accepted desc); 
CREATE INDEX ON friend_list (accepted); 

有了這個B型模式,第1和第2的查詢工作,但我可以簡化第三個查詢爲:

3. SELECT * FROM friend_list WHERE userId="---"; 

我認爲,第二個架構給出了第三個查詢更好的性能,因爲它不會對每一行進行條件檢查。

卡桑德拉專家......請建議我這是在實現this.A或B.

回答

1

首先最好的模式,你知道你的第二個架構完全不一樣工作的第一個?在第一個「接受」領域是關鍵的一部分,但在第二個沒有!你沒有相同的唯一約束,你應該檢查它對你的模型不是問題。

其次,如果你只是想沒有包括「詞義」字段爲每一個請求有兩個可能性:

1 - 您可以使用「詞義」作爲一個集羣列:

PRIMARY KEY ((userId), accepted, ts_accepted) 

這樣你的第三個請求可以是:

SELECT * FROM friend_list WHERE userId="---"; 

你會更有效地得到相同的結果。

但是這種方法有問題,它會創建更大的分區,這不是最好的表現。

2 - 創建兩個單獨的表

這種做法是卡桑德拉精神更加充足。使用Cassandra時,如果可以提高請求的效率,則複製數據並不少見。

所以你的情況,你會保持你的第一個模式的第一個表,並在第一和第二個請求,

,你會創建另一個表使用相同的數據,但一個模式略有不同,或者與二級索引如果「接受」並不需要是主鍵的一部分(如你爲你的第二個模式),或者這樣的主鍵:

PRIMARY KEY ((userId), accepted, ts_accepted) 

我肯定會喜歡的二級指數爲第二個表如果可能的話,因爲接受的列具有低基數(2),因此非常適合二級索引。

編輯:

此外,你在你的主鍵使用時間戳。請注意,如果您有相同的用戶在此表中創建兩行,則可能會出現問題。由於時間戳不保證唯一性:如果兩行創建的毫秒數相同,會發生什麼?

您應該使用TimeUUID。 Cassandra中非常常用的這種類型通過組合Timestamp和UUID來保證唯一性。

此外,主鍵中的時間戳可以在Cassandra節點中創建臨時熱點,絕對是避免的。

+0

所以你建議有兩個表,首先是我的模式A查詢1和2,第二個表我的模式B查詢3。但爲什麼我不能只用模式B作爲所有3個查詢作爲主要被接受的密鑰不是必需的。 –

+0

此外,如果我使用PRIMARY KEY((userId),接受,ts_accepted),我不能排序ts_accepted集羣列順序,因爲我必須排序'accepted'和'ts_accepted'。每次不必要地排序'接受'會帶來性能問題。 –

+1

您的第一個模式似乎表明您需要主鍵中的'accepted'字段。如果你不那麼爲你的特定用例,我認爲是索引列是好的(低基數,罕見的變化),但它仍然比'接受'作爲一個聚類列慢。雖然對於你的情況,差異應該是最小的。 – sam