NoSQL那些事:51CTO帶您走進(jìn)列數(shù)據(jù)庫(kù)
原創(chuàng)【51CTO外電頭條】列數(shù)據(jù)庫(kù)出名可能是因?yàn)镚oogle BigTable的出現(xiàn),它表面上和關(guān)系數(shù)據(jù)庫(kù)類(lèi)似,但實(shí)際上卻有著本質(zhì)的不同,一個(gè)是按行存儲(chǔ)數(shù)據(jù)(關(guān)系數(shù)據(jù)庫(kù)),一個(gè)是按列存儲(chǔ)數(shù)據(jù)(列數(shù)據(jù)庫(kù))的,你不能將適用于關(guān)系數(shù)據(jù)庫(kù)的解決方案強(qiáng)加給列數(shù)據(jù)庫(kù),因?yàn)榱袛?shù)據(jù)庫(kù)是沒(méi)有關(guān)系的。51CTO數(shù)據(jù)庫(kù)頻道向您推薦《NoSQL:關(guān)系型數(shù)據(jù)庫(kù)的終結(jié)者?》專(zhuān)題,以便于您更好的理解NoSQL。
搞清楚下面幾個(gè)概念才能理解列數(shù)據(jù)庫(kù)是如何工作的:
◆Column Family
◆Super Column
◆Column
列數(shù)據(jù)庫(kù)中的Column和Super Column是不占位的,意味著如果它們里面沒(méi)有值,它們只占用0字節(jié),Column Family與傳統(tǒng)數(shù)據(jù)庫(kù)中的表類(lèi)似,但和表又不一樣,在Column Family中的唯一定義是名稱(chēng)和鍵(Key)排序選項(xiàng)(沒(méi)有任何模式)。
我個(gè)人認(rèn)為Column Family數(shù)據(jù)庫(kù)(CFDB)可能是消除抽象設(shè)計(jì)的最佳方法,因?yàn)镃FDB中的一切都是圍繞真實(shí)的物理模型的。
◆Column Family – Column Family指定數(shù)據(jù)如何存儲(chǔ)在磁盤(pán)上的,一個(gè)Column Family中的所有數(shù)據(jù)都將保存在相同的文件中,一個(gè)Column Family可以容納多個(gè)Super Column或Column。
◆Super Column - Super Column是一個(gè)字典,它是一個(gè)包含其它列的列,但一個(gè)Super Column不能包含另一個(gè)Super Column。
◆Column - Column是一個(gè)由名稱(chēng),值和時(shí)間戳組成的三元組(我將忽略時(shí)間戳,把它當(dāng)作一個(gè)Key/Value對(duì)看待)。
最重要的是要明白CFDB架構(gòu)設(shè)計(jì)的外圍重要性,如果架構(gòu)都不正確,那基本上就無(wú)法獲取數(shù)據(jù),CFDB通常按照鍵或鍵范圍提供一兩種形式的查詢(xún),這是很有意義的,因?yàn)镃DFB通常是分布式的,鍵決定了數(shù)據(jù)的真實(shí)物理位置,這是因?yàn)閿?shù)據(jù)是基于Column Family的排序順序存儲(chǔ)的,你是沒(méi)有辦法改變排序方式的(除了選擇升序和降序外)。
和關(guān)系數(shù)據(jù)庫(kù)中的排序順序不一樣,列數(shù)據(jù)庫(kù)的排序順序不受列的值影響,只受列名的影響。
假設(shè)在Users Column Family,@ayende行中,我們將列“name”設(shè)為“Ayende Rahine”,列“location”設(shè)為“Israel”,CFDB將會(huì)象Users Column Family文件一樣對(duì)它們進(jìn)行排序:
- @ayende/location = “Israel”
 - @ayende/name = “Ayende Rahien”
 
這是因?yàn)榕判驎r(shí)“location”小于“name”的緣故,如果在Friends Column Family中有一個(gè)Super Column,用戶(hù)“@ayende”有兩個(gè)朋友,它們將會(huì)象Friends Column Family文件那樣進(jìn)行存儲(chǔ):
- @ayende/friends/arava= 945
 - @ayende/friends/rose = 14
 
記住,這個(gè)屬性對(duì)理解CFDB是如何工作的相當(dāng)重要,我們以Twitter模型為例,我們需要存儲(chǔ):用戶(hù)和推(tweet),我們定義了三個(gè)Column Family:
◆Users – 按UTF-8排序
◆Tweets – 按連續(xù)GUID排序
◆UsersTweets - Super Column Family,按連續(xù)GUID排序
我們創(chuàng)建一個(gè)用戶(hù)(我使用name參數(shù)標(biāo)志列名和值,key參數(shù)表示行的鍵,Column Family是Users):
- cfdb.Users.Insert(key: “@ayende”, name: “Ayende Rahine”, location: “Israel”, profession: “Wizard”);
 
下圖是一個(gè)可視化的表示,注意與關(guān)系數(shù)據(jù)庫(kù)的區(qū)別。

圖 1 保存用戶(hù)信息的存儲(chǔ)樣式
現(xiàn)在我們創(chuàng)建一個(gè)推:
- var firstTweetKey = “Tweets/” + SequentialGuid.Create();
 - cfdb.Tweets.Insert(key: firstTweetKey, application: “TweekDeck”, text: “Err, is this on?”, private: true);
 - var secondTweetKey = “Tweets/” + SequentialGuid.Create();
 - cfdb.Tweets.Insert(key: secondTweetKey, app: “Twhirl”, version: “1.2”,
 - text: “Well, I guess this is my mandatory hello world”, public: true);
 
下面是它真實(shí)的存儲(chǔ)格式:

圖 2 保存推信息的存儲(chǔ)樣式
這里有幾件事需要注意:
◆在這里,Key不重要,重要的是它是連續(xù)的,因?yàn)楹竺鏁?huì)根據(jù)它進(jìn)行排序;
◆兩個(gè)行上面有不同的數(shù)據(jù)列;
◆我們實(shí)際上沒(méi)有任何方法將用戶(hù)和推關(guān)聯(lián)起來(lái)。
在關(guān)系數(shù)據(jù)庫(kù)中,我們通常會(huì)定義一個(gè)名叫UserId的列,這樣我們可以通過(guò)它將推鏈接回用戶(hù),此外,關(guān)系允許我們按用戶(hù)ID查詢(xún)推,但CFDB沒(méi)有這樣的功能,無(wú)法根據(jù)列的值進(jìn)行查詢(xún),也沒(méi)有辦法按照列進(jìn)行查詢(xún),CFDB只能根據(jù)鍵查詢(xún),我們以UsersTweets Column Family為例進(jìn)行說(shuō)明:
- cfdb.UsersTweets.Insert(key: “@ayende”,
 - timeline: { SequentialGuid.Create(): firstTweetKey } );
 - cfdb.UsersTweets.Insert(key: “@ayende”,
 - timeline: { SequentialGuid.Create(): secondTweetKey } );
 
在CFDB上,它看起來(lái)象:

圖 3 用戶(hù)和推關(guān)聯(lián)
這里我們向UsersTweets Column Family插入數(shù)據(jù),行的Key是“@ayende”,Super Column timeline有兩列,每個(gè)列的名字是一個(gè)連續(xù)的GUID,這意味著我們可以根據(jù)它進(jìn)行排序,實(shí)際上我們是用一個(gè)Super Column創(chuàng)建了一個(gè)行,它又包含兩列,列名是一個(gè)GUID,每一列的值是Tweets表中一個(gè)行的鍵。
問(wèn)題:我們可以在Users Column Family中創(chuàng)建一個(gè)Super Column存儲(chǔ)關(guān)系嗎?是的,可以這么做,但一個(gè)Column Family要么容納Super Column,要么容納Column,不能二者兼得。
為了獲得某個(gè)用戶(hù)發(fā)的推,我們需要執(zhí)行:
- var tweetIds =
 - cfdb.UsersTweets.Get(“@ayende”)
 - .Fetch(“timeline”)
 - .Take(25)
 - .OrderByDescending()
 - .Select(x=>x.Value);
 - var tweets = cfdb.Tweets.Get(tweetIds);
 
從本質(zhì)上來(lái)講,我們執(zhí)行了兩個(gè)查詢(xún),一個(gè)是在UsersTweets Column Family執(zhí)行的,用行鍵“@ayende”請(qǐng)求timeline Super Column中的列和值,然后在Tweets Column Family上執(zhí)行另一個(gè)查詢(xún),獲得真正的推。
因?yàn)閿?shù)據(jù)是按照列名排序的,同時(shí)我們選擇的是降序排序,我們獲得了該用戶(hù)的最后25個(gè)推。
如果我想展示最后25個(gè)推該怎么辦?很簡(jiǎn)單,只需要查詢(xún)Tweets Column Family中的推,然后按鍵倒序排序即可。
為什么CFDB有如此多的限制?
你可能已經(jīng)注意到我多次提及RDBMS和CFDB的差異,我認(rèn)為CFDB理解起來(lái)確實(shí)有點(diǎn)難,即使它表面上和關(guān)系數(shù)據(jù)庫(kù)很接近,但它的限制卻很多,沒(méi)有連接,沒(méi)有真正的查詢(xún)功能(除了主鍵外),越是熟悉關(guān)系數(shù)據(jù)庫(kù),對(duì)理解CFDB越是有影響。
之所以有這么多的限制,主要原因是CFDB設(shè)計(jì)目標(biāo)就是運(yùn)行在多臺(tái)機(jī)器上,存儲(chǔ)大量信息的,在關(guān)系數(shù)據(jù)庫(kù)中幾乎是不可能存儲(chǔ)這么多數(shù)據(jù)的,即使是象Oracle RAC這樣的集群數(shù)據(jù)庫(kù)也存儲(chǔ)不了那么多數(shù)據(jù)。
CFDB不提供連接的原因是,連接需要你能掃描整個(gè)數(shù)據(jù)集,這個(gè)時(shí)候要么使用一個(gè)視圖,否則就只有掃描整個(gè)數(shù)據(jù)庫(kù)了,這會(huì)造成性能急劇下降,因此CFDB必須避免出現(xiàn)這種情況。
CFDB不提供按列或按值查詢(xún)的原因是,因?yàn)檫@樣要么需要一個(gè)索引,要么掃描整個(gè)數(shù)據(jù)集,CFDB將查詢(xún)限制到只能按鍵進(jìn)行查詢(xún),確保它能準(zhǔn)確地知道查詢(xún)應(yīng)在哪個(gè)節(jié)點(diǎn)上運(yùn)行,這意味著每個(gè)查詢(xún)只會(huì)掃描一小段數(shù)據(jù)集,性能自然會(huì)好很多。
理解列數(shù)據(jù)庫(kù)需要一種截然不同的思維方式,雖然我沒(méi)有CFDB實(shí)戰(zhàn)經(jīng)驗(yàn),我可以想像得到,使用它們遷移是個(gè)麻煩事,但它確實(shí)是獲得高可擴(kuò)展數(shù)據(jù)存儲(chǔ)的最好方式。
到最后,51CTO數(shù)據(jù)庫(kù)的編輯了解到,有些專(zhuān)業(yè)人士還是認(rèn)為列數(shù)據(jù)庫(kù)也不全是NoSQL。盡管有Sybase IQ這樣的產(chǎn)品,但是列數(shù)據(jù)庫(kù)當(dāng)中還是有關(guān)系存在的。
作者簡(jiǎn)介

Ayende Rahien只是網(wǎng)名,作者的真實(shí)名字叫做Oren Eini,他是一名經(jīng)驗(yàn)豐富的開(kāi)發(fā)人員/架構(gòu)師,主要精力放在CLR,構(gòu)建商業(yè)應(yīng)用和開(kāi)發(fā)生產(chǎn)力框架和工具上,他也是多個(gè)著名開(kāi)源項(xiàng)目的積極成員,包括NHibernate,Castle等,另外,Oren Eini還創(chuàng)建了多個(gè)開(kāi)源項(xiàng)目,如Rhino Mocks,NHibernate Query Analyzer,Rhino Commons等。
原文出處:ayende.com/Blog/archive/2010/05/14/that-no-sql-thing-Column-family-databases.aspx
【編輯推薦】
- 用NoSQL來(lái)替代MySQL在Digg中的原因
 - MongoDB CEO談NoSQL的大數(shù)據(jù)量處理能力
 - 51CTO專(zhuān)訪(fǎng)蓋國(guó)強(qiáng):NoSQL很火 但還需市場(chǎng)檢驗(yàn)
 - 詳解NoSQL數(shù)據(jù)庫(kù)使用實(shí)例
 - 云計(jì)算時(shí)代NoSQL當(dāng)?shù)?關(guān)系數(shù)據(jù)庫(kù)日薄西山
 















 
 
 



 
 
 
 