2011-08-18 100 views
2

我正試圖將一個RDBMS模型轉移到Cassandra,並且很難創建模式。這裏是我的數據模型:MySQL數據模型到Cassandra的幫助?

CREATE TABLE Domain (
    ID INT NOT NULL PRIMARY KEY, 
    DomainName NVARCHAR(74) NOT NULL, 
    HasBadWords BIT, 
    ... 
); 
INSERT INTO Domain (DomainName, HasBadWords) VALUES ('domain1.com', 0); 
INSERT INTO Domain (DomainName, HasBadWords) VALUES ('domain2.com', 0); 

CREATE TABLE ZoneFile (
    ID INT NOT NULL PRIMARY KEY, 
    DomainID INT NOT NULL, 
    Available BIT NOT NULL, 
    Nameservers NVARCHAR(MAX), 
    Timestamp DATETIME NOT NULL 
); 
INSERT INTO ZoneFile (DomainID, Available, Nameservers, Timestamp) VALUES (1, 0, "ns1", '2010-01-01'); 
INSERT INTO ZoneFile (DomainID, Available, Nameservers, Timestamp) VALUES (2, 0, "ns1", '2010-01-01'); 
INSERT INTO ZoneFile (DomainID, Available, Nameservers, Timestamp) VALUES (1, 1, "ns2", '2011-01-01'); 
INSERT INTO ZoneFile (DomainID, Available, Nameservers, Timestamp) VALUES (2, 1, "ns2", '2011-01-01'); 

CREATE TABLE Backlinks (
    ID INT NOT NULL PRIMARY KEY, 
    DomainID INT NOT NULL, 
    Backlinks INT NOT NULL, 
    Indexed INT NOT NULL, 
    Timestamp DATETIME NOT NULL 
); 
INSERT INTO Backlinks (DomainID, Backlinks, Indexed, Timestamp) VALUES (1, 100, 200, '2010-01-01'); 
INSERT INTO Backlinks (DomainID, Backlinks, Indexed, Timestamp) VALUES (2, 300, 600, '2010-01-01'); 
INSERT INTO Backlinks (DomainID, Backlinks, Indexed, Timestamp) VALUES (1, 500, 1000, '2010-01-01'); 
INSERT INTO Backlinks (DomainID, Backlinks, Indexed, Timestamp) VALUES (2, 600, 1200, '2010-01-01'); 

從這裏我推斷出我可能有一個Keyspace:DomainData。在這個密鑰空間,我可以有一個名爲的ColumnFamily「域」,它就像我的域名錶中的SQL:

"Domain" : { //ColumnFamily 
    "domain1.com" : { "HasBadWords" : 0 }, //SuperColumn 
    "domain2.com" : { "HasBadWords" : 0 } //SuperColumn 
} 

下表是在那裏我開始感到困惑。 ZoneFile和Backlinks本質上應該是通過查找每個域的這些值來存儲結果的歷史記錄。所以,一個域到多個ZoneFile記錄。爲了查詢目的,我希望能夠輕鬆獲得'最新的'ZoneFile記錄或給定的域。我需要爲Backlinks做同樣的事情。

我正在考慮這樣的事情,而且按鍵上做了一系列的查找域,然後讓這應該是最新的時間戳「最後」的記錄......

"ZoneFiles" : { //ColumnFamily 
    "domain1.com:2010-01-01 12:00:00.000" : { "Available" : 0, "Nameservers" : "ns1" }, //SuperColumn 
    "domain1.com:2011-01-01 12:00:00.000" : { "Available" : 1, "Nameservers" : "ns2" }, //SuperColumn 
    "domain2.com:2010-01-01 12:00:00.000" : { "Available" : 0, "Nameservers" : "ns1" }, //SuperColumn 
    "domain2.com:2011-01-01 12:00:00.000" : { "Available" : 1, "Nameservers" : "ns2" } //SuperColumn 
} 

我不相信這是正確的答案,字符串域和字符串日期時間組合在一個鍵中感覺不對。有人能指出我正確的方向嗎?

編輯:

假設我用:

"ZoneFiles" : { 
    "domain1.com" : { 
    timestamp1 : "{\"available\":1,\"nameservers\":\"ns1\"}", 
    timestamp2 : "{\"available\":1,\"nameservers\":\"ns1\"}", 
    } 
} 

我將如何查詢域名行的名單,其中最新的時間戳比一個給定日期的?

回答

4

如果我正確理解你的問題,你想要在這個模型上做的唯一的查詢是「請給我一個給定的域的最新的區域文件或反向鏈接」?

如果是這種情況,我會將這些值的最新值存儲在「域」列家族中的域行鍵下的單獨列中。當這個最新值更新時(時間戳),我也會存儲。每當您爲zonefile和反向鏈接中的信息獲取新值時,我只會覆蓋「域」列族中的值並更新時間戳。

我假設你也保存了這個歷史數據,以便你可以查詢它,我假設這種查詢將「在兩次之間顯示給定域的所有更新」(這是否正確?)。如果是這樣,我不會像那樣手動構造一個複合行鍵,因爲它要求您使用Order Preserving Partitioner從get_range_slices中獲取正確的結果。正如您可能知道的那樣,使用OPP進行負載均衡可能是一項艱鉅的任務。

相反,我會將行鍵設爲域ID,而列鍵爲更新的時間戳。然後,您可以將更新打包爲單個值(例如,使用json),使用超級列或使用0.8中的新組合鍵。如果這樣做,您可以使用get_slice來滿足您的查詢,並且它將在隨機分區程序中正常運行,從而使負載平衡更容易。

Tom Wilkie | Acunu | www.acunu.com | @tom_wilkie

回覆評論:「我將如何查詢最近zonefile時間戳列的域列表比給定時間戳更早的域列表?「

你可以做,通過插入到另一個列族:

row key: day (or hour, or some other reasonable 'bucketing') 
column key: timestamp of update 
value: domain 

...每次更新zone數據文件。然後,讓因爲T最近更新的領域,這樣做:

result = [] 
for i in day(t) ... day(now): 
    result.extend(get_slice(i, range(t, ''))) 

這將要求您從結果中刪除重複的條目,所以只有當t很近時纔會工作得最好,您還必須考慮寫入的負載平衡,這會將所有負載集中在單個服務器上因爲在任何時候,你都是插入到只有一行)

如果這些權衡不合適,那麼你可以看看hadoop集成並使用它來執行此查詢。或者你可以做其他的權衡(使用OPP,或者在寫入之前做一個讀取來刪除重複項,這會很慢)

+0

我喜歡你要去的地方...我編輯過問題假設一個時間戳作爲列名和json打包數據。 – Redth

+0

現在,假設我將如何查詢最近zonefile時間戳列的域比給定時間戳更早的域列表? – Redth

+0

謝謝,我已經有效地完成了你的建議,儘管我最終使用MongoDB在我的查詢中獲得了更多的靈活性,這是將當前值非規範化並將它們粘在域文檔中的主要概念,文件爲每個領域和歷史...乾杯! – Redth