2015-03-31 63 views
3

我有一個用戶模型,其特徵如下: -Cassandra-數據建模UserProfilie

class User(Model): 
    user_id = columns.Integer(primary_key=True) 
    username = columns.Text() 
    email = columns.Text() 
    fname = columns.Text() 
    lname = columns.Text() 
    age = columns.Text() 
    state = columns.Text() 
    city = columns.Text() 
    country = columns.Text() 
    gender = columns.Text() 
    phone = columns.Text() 
    school_name = columns.Text() 
    created_at = columns.Text() 
    race = columns.boolean() 

這是我的正常RDBMS模型。我的查詢如下: -

1) Get all users with city = 'something' 

2) Get a user with email = 'something' 

3) Get a user with username = 'something' 

4) Get all users with phones IN ('something') 

5) Get all users with state = 'something' 

6) Get all users with age > something 

7) Get all users with gender = 'something' 

8) Get all users with race = 'something' 

9) Get count(*),school_name users Group By schoolname 

10) Get all users with created_date > 'something' LIMIT 1000 

11) Get all users with username IN ('something') AND age IN ('something') AND phone IN ('something') AND state IN ('something') AND so on LIMIT 1000 

我可以得到上述結果與數據庫管理系統的一個簡單的選擇查詢的查詢,但問題在於卡桑德拉。

因爲爲了在Cassandra中獲得上述查詢的結果,建議每個查詢都有一個不同的模型,這將加快讀取能力。在這個時代,磁盤比以前更便宜。這就是說,我明白,只是拋出更多磁盤來解決問題並不總是容易的。我看到的更大的問題是調整應用程序的DAO層以保持10個不同的表同步。 (另外,我的內心本能並不認爲有10個模型適用於不同的查詢:P)

可以請某人解釋我在卡桑德拉的合適模型以獲得這些查詢的結果嗎?

PS:對上述模型的操作可以是Read/Write/Update/Delete。 查詢11是最重要的查詢。

考慮到有關特定用戶的信息可以更新,最重要的是使這些查詢在大量數據上真正快速。

回答

0

您正面臨真正的Cassandra限制:如果您確定要與Cassandra一起使用需要遵循「卡桑德拉規則」。這其中有

  • 去正規化
  • 選擇指數明智

因此,讓我們開始吧。每個用戶應該有唯一的ID,用戶名,電子郵件和電話。這意味着這些列不適合索引(read here why),所以非規範化是正確的方法。

從您的查詢中,您將擁有user_by_username,user_by_email和user_by_phones。您可能認爲每次重複數據在更新和磁盤使用方面可能都很麻煩:因此,您可以通過創建每個僅包含用戶ID的值作爲折衷方案來妥協。即g:

user_email  | user_id 
--------------+------------------- 
[email protected] | 123-456-7aa |  
[email protected] | efg-123-ghi | 

在KS內部的另一個表中,您需要一個表格,通過id將檢索關於用戶的所有信息。這將解決update problem,如果您需要更新電子郵件地址或手機,則只能更新多個表而不是N個。不好的一面是您必須執行兩個查詢來獲取數據。

讓我們繼續。

stategenderrace是被索引,原因如下很好的候選人:

  1. 低基數
  2. 許多行會包含這些值

通過索引你將解決一些其他查詢。最難的部分是這種類型的查詢時,就不會允許卡桑德拉像

select * from users where age > xyz 

查詢,因爲你需要在叢集部分執行!「等於」操作。要做到這一點,您需要通過某種常用密鑰來「組織」用戶:如狀態或「狀態組」 - 這意味着要了解具有特定年齡的所有用戶,您必須查詢每個分區。

小心:我沒有提供解決方案,這不是我的目標 - 我試圖做的是提供一種方法來解決Cassandra的這個問題。

HTH,
卡羅

+0

感謝@Carlo提供一種可能的方法對上述問題的深度解讀。最後一個問題。如果將來,我決定寫一個涉及'過濾用戶狀態'的查詢,那麼我需要創建另一個列家族? **如我錯了請糾正我**。因此,爲了創建另一個列族,我需要將其他CF中的數據遷移(複製)到最新的bulit CF中。不是嗎? – PythonEnthusiast 2015-04-07 09:56:39

+0

是的,您是對的:如果您需要使用新查詢獲得過去數據的信息,那麼您已經將這些數據遷移到新表中 – 2015-04-07 10:14:48

+0

但是之後它再次成爲手動操作,將數億行數據從CF複製到另一個。由於我無法在一開始就凍結我的所有要求,因此您對此有何看法? – PythonEnthusiast 2015-04-07 10:21:59

1

可能最簡單的方法是使用Datastax Enterprise和Search(Solr)或Analytics(Spark)選項。您可以免費從www.datastax.com下載以用於測試目的。只要您的SLA數據可用於查詢超過1秒,lucene索引應該能夠處理這些不同的搜索選項。

更大的問題是爲什麼你想在這裏使用卡桑德拉?你說的大量數據是什麼意思?通常,當您的應用程序具有低延遲讀寫需求,可以複製到許多服務器和許多數據中心以及沒有停機時間時,Cassandra的功能最佳。這在數據集市/倉庫或分析數據庫中通常不是必需的,通過查詢類型和您需要在「大量數據」上執行該操作似乎指出了這一點。每個Cassandra節點通常不會放置超過1 - 3T的數據,儘管這裏有一些異常值...