第一章 概述
1.2.1 關系型數(shù)據(jù)庫
Relational DataBase Management System, 實現(xiàn)為具有行和列的二維表霸妹。交互標準是SQL慈参。值類型可以是數(shù)字八拱,字符串戏自,日期呀酸,二進制厅篓。mysql响驴,H2透且,HSOLDB,SQLite豁鲤,后續(xù)主要說PostgreSQL
1.2.2 鍵值數(shù)據(jù)庫
在一些場景下有令人難以置信的高性能秽誊,但是當你有復雜的查詢和聚合需求時,它一般不會有幫助琳骡。
1.2.3 列型數(shù)據(jù)庫
在面向列的數(shù)據(jù)庫中锅论,添加列是相當容易的,而且是逐行完成的楣号。每一行可以有不同的列最易,或者完全沒有,允許表保持稀疏炫狱,而不會產(chǎn)生空值的存儲成本藻懒。
1.2.4 文檔型數(shù)據(jù)庫
文檔數(shù)據(jù)庫存儲的就是文檔。簡而言之视译,文檔就是hash嬉荆,具有獨一無二的標識符字段和值,值可能是任何類型酷含,包括更多的hash鄙早。文檔可以包含嵌套的結構,因此表現(xiàn)出了高度的靈活性第美,允許有可變域蝶锋。在建索引,自由定義的查詢什往,復制扳缕,一致性及其他設計決策等方面,不同的文檔數(shù)據(jù)庫采取了不同的方法。
1.2.5 圖數(shù)據(jù)庫
圖數(shù)據(jù)庫善于處理高度互聯(lián)的數(shù)據(jù)躯舔。圖數(shù)據(jù)庫包含節(jié)點與節(jié)點之間的關系驴剔。節(jié)點和關系可以有一些屬性,用來存儲數(shù)據(jù)粥庄。圖數(shù)據(jù)庫真正實力是按照關系遍歷節(jié)點丧失。
1.2.6 混合使用多種數(shù)據(jù)庫
第二章 PostgreSQL
關系型數(shù)據(jù)庫流行的原因,不近在于其龐大的特性集(高級索引)惜互、數(shù)據(jù)的安全性(ACID)布讹,或符合大多數(shù)人的斯文方式,還在于它們的查詢靈活性训堆。
2.1 這就是post-gre-s-q-l
PostgreSQL是歷史最悠久描验,實戰(zhàn)經(jīng)驗最豐富的。它的擴展包括自然語言解析坑鱼、多維索引膘流、地理查詢、自定義數(shù)據(jù)類型等鲁沥。具有高級的事務能力呼股,支持十幾種不同語言的存儲過程。PostgreSQL內(nèi)置支持Unicode画恰、序列彭谁、表繼承、子查詢阐枣,快速可靠马靠,可以處理TB級別的數(shù)據(jù)。
2.2 第一天:關系蔼两。CRUD和聯(lián)接
關系數(shù)據(jù)庫的關系是因為它的數(shù)學基礎,不是因為它通過外鍵彼此“關聯(lián)”逞度。這樣的限制是否存在并不關鍵额划。
雖然許多數(shù)學關系你看不到,但是模型的力量肯定是蘊藏在數(shù)學之中档泽。這種魔法允許用戶提供功能強大的查詢俊戳。
2.3.3 窗口函數(shù)
在mysql中,如果你試圖select一些沒有在group by中限定的列馆匿,你可能會吃驚的看到抑胎,它有結果。這讓我們開始懷疑窗口函數(shù)的必要性渐北。但更細致的檢查mysql返回的數(shù)據(jù)之后阿逃,我們發(fā)現(xiàn)它返回的只是一些隨機的數(shù)據(jù)行和計數(shù),并非所有相關的結果。一般來說這是沒用的(而且可能相當危險)恃锉。
2.4.2 SQL標準的字符串匹配
PostgreSQL有很多方法進行文本匹配搀菩,但是兩大默認方法是LIKE和正則表達式
- LIKE和ILIKE
select title from moives where title ilike 'stardust%'
有個小技巧,如果想確保子串stardust不在字符串的末尾可以使用下劃線(_)字符破托。
select title from moives where title ilike 'stardust_%'
p.s. 估計現(xiàn)在很少有公司用like吧
- 正則表達式
PostgreSQL采用POSIX風格的正則表達式肪跋。在PostgreSQL中,正則表達式的匹配字串由~
運算符開始土砂,還可以帶有可選的!
(意思是不匹配)和*
(意思是不區(qū)分大小寫)州既。
select count(*) from moives where title !~* '^the.*'
可以為前面查詢的模式創(chuàng)建字符串索引,
create index moives_title_pattern on movies(lower(title) text_pattern_ops);
2.4.3 字符串相似比較算法levenshtein
levenshtein是一個字符串比較算法萝映,它能夠計算一個字符串需要經(jīng)過多少步才能變成另一個字符串吴叶,從而可能比較兩個字符串的相似程度。
select levenshtein('bat','fad') fad,
levenshtein('bat', 'fat') fat,
levenshtein('bat', 'bat') bat
2.4.5 全文檢索
- TSVector和TSQuery
查找包含night和day的數(shù)據(jù)
select title from moives where title @@ 'night&day'
@@
將電影名稱轉(zhuǎn)換成tsvector結構體锌俱,并將查詢轉(zhuǎn)換成tsquery結構體晤郑。
select title from moives where to_tsvector(title) @@ to_tsquery('english', 'night&day')
我們來看下向量和查詢?nèi)绾螌⒆址珠_
select to_tsvector('A hard day's night), to_tsquery('english', 'night&day')
to_tsvector | to_tsquery |
---|---|
'day':3, 'hard':2, 'night':5 | 'night'&'day' |
- 對詞素索引
全文檢索功能雖然強大。但是如果不創(chuàng)建相關的索引贸宏,檢索的速度會很慢造寝。explain是個強大的工具,可以查看內(nèi)部執(zhí)行計劃吭练。當執(zhí)行計劃出現(xiàn)seq scan on table
時基本上都不是什么好現(xiàn)象诫龙,我們通過創(chuàng)建反向索引,但是查詢同時要指定語言鲫咽。例如:
select title from moives where to_tsvector('english', title) @@ 'night & day'
- 發(fā)音碼metaphone
2.5.1 PostgreSQL的優(yōu)點
2.5.2 PostgreSQL的缺點
PostgreSQL這樣的關系數(shù)據(jù)庫签赃,分區(qū)不是強項。如果需要水平擴展而不是垂直擴展可能最好尋找其他解決方案分尸。
第三章 Riak(讀作Ree-ahck)
Riak是一種分布式的鍵值數(shù)據(jù)庫锦聊。其中值可以是任何類型的數(shù)據(jù);而且都能通過http接口訪問箩绍。容錯性是RIak的另一個特性孔庭。服務器可在任何時刻啟動或者停止,而不會引起任何單點故障材蛛。不管是增減或者移除服務器圆到,甚至有節(jié)點崩潰,集群依然可以持續(xù)忙碌的運行卑吭。Riak讓你不再整夜無眠擔心集群芽淡,某個節(jié)點失效不再是緊急事件,完全可以等到第二天處理豆赏。然而萬事都有利弊取舍挣菲,Riak的靈活性自有代價富稻,對于自由定義的查詢,Riak缺乏有力支持己单;而鍵值存儲的設計使得數(shù)據(jù)無法相互連接唉窃。
3.1 Riak喜歡web
可以通過URL,HTTP頭纹笼,HTTP方法查詢
3.2 第一天纹份;CRUD、鏈接和MIME
3.3.4 關于一致性和持久性
將數(shù)據(jù)分布于多個服務器必須面對一個棘手的先天問題廷痘。如果你想要數(shù)據(jù)庫在網(wǎng)絡分區(qū)發(fā)生時依然能夠運行蔓涧,你必須做一個權衡∷穸睿或者對服務器請求保持可用元暴,或者拒絕請求,以保證數(shù)據(jù)的一致性兄猩。要創(chuàng)建一個具備完全一致性茉盏、可用性與分區(qū)容錯性的分布式數(shù)據(jù)庫,是不可能的枢冤。Riak允許在每個請求的基礎上鸠姨,以可用性交換一致性。我們先看Riak如何將服務器組成集群淹真,然后討論如何調(diào)整讀寫來和集群交互讶迁。
Riak環(huán)
Riak將其服務器配置劃分為分區(qū),以一個160比特的數(shù)字表示核蘸。把一個鍵hash為一個分區(qū)巍糯,這個環(huán)會幫忙指向存有響應值的服務器。在搭建一個Riak集群式客扎,遇到的第一個問題就是你想要多少個分區(qū)祟峦,不妨考慮這樣一個案例,你有64個分區(qū)(默認)徙鱼。如果把這64個分區(qū)分布在3個節(jié)點上搀愧,Riak會為每個節(jié)點分配21或者22個分區(qū)。每個分區(qū)為一個虛擬節(jié)點疆偿,或者vnode。每個Riak服務會在啟動時計數(shù)搓幌,依次清點分區(qū)直到所有的vnode都清點完畢杆故。每個vnode代表一系列經(jīng)過hash的鍵。當插入鍵101的客房數(shù)據(jù)時溉愁,它會hash到vnode2的范圍处铛,于是鍵值對象會存儲在節(jié)點B上饲趋。Riak允許通過改變?nèi)齻€值:N,W與R撤蟆,來控制集群的讀寫奕塑。N是一次寫入最終復制到的節(jié)點數(shù)量,換句話說家肯,就是集群中的副本數(shù)量龄砰。W是一次成功的寫入響應之前,必須成功寫入的節(jié)點數(shù)量讨衣。如果W<N换棚,就認為某次寫入是成功的,及時Riak依然在復制數(shù)據(jù)反镇。最后R是成功讀出一項數(shù)據(jù)所必須的節(jié)點數(shù)量固蚤。如果R比可用的復制數(shù)量大,讀出請求將失敗歹茶。舉個例子:如果N=4夕玩,W=2那么在寫入兩個節(jié)點成功之后就會返回成功,后臺復制其他節(jié)點惊豺。這樣能更快響應燎孟。如果把NRW設置成{"v_val":3, "r":2, "w":1},這種設置使系統(tǒng)寫入的操作響應快扮叨,但是存在另一種可能缤弦,恰巧在節(jié)點同步之前,另一個讀出操作執(zhí)行了彻磁,那么讀到的值可能是錯誤的碍沐。一種確保我們能夠讀到最新值的方法是讓W=N,R=1衷蜓。從本質(zhì)上講累提,這就是關系型數(shù)據(jù)庫的做法;通過確保寫操作在返回之前完成磁浇,以保證一致性斋陪。但是這確實會降低寫操作的性能≈孟牛或者无虚,可以只寫入單點,從而從全部節(jié)點讀出衍锚,讓R=N友题,W=1,盡管你可能因此讀到一些舊值戴质,但你也能保證檢索到最新的值度宦,這時你需要做的是找出哪些是最新的值踢匣。當然這也會帶來副作用,讀操作會因此減慢戈抄。還有一種選擇离唬,只需要寫入多余一半的節(jié)點,并且從多余一半的節(jié)點讀出划鸽,就依然保證了一致性输莺。同時,分擔介于讀寫之間的延時漾稀。這成為法定數(shù)模闲,是確保數(shù)據(jù)一致性的方法中開銷最小的。
Riak的寫入操作未必是持久化的崭捍,也就是說并非立即寫入磁盤尸折。及時一個節(jié)點的寫入操作執(zhí)行成功,依然可能因為故障而丟失殷蛇,寫入磁盤之前实夹,會在內(nèi)存中緩存片刻,而這毫秒的間隙正是危險的所在粒梦。但是Riak提供了名為DW的單獨設置亮航,用于持久化寫入。但是同樣會減慢速度匀们。
關于臨時轉(zhuǎn)移缴淋,嘗試寫入不可用的節(jié)點仍然會執(zhí)行成功,并得到這樣的返回“204 No content”泄朴。這是因為Riak會把數(shù)據(jù)先寫入附近的一個節(jié)點重抖,該節(jié)點一直保存數(shù)據(jù),直到它能將這些數(shù)據(jù)交給不可用的節(jié)點祖灰。但是因為一個服務的負載編程雙倍導致級聯(lián)故障钟沛,需要注意。
3.4.1 以向量時鐘解決沖突
由于若干客戶端可能鏈接到不同的服務器局扶,并且一個客戶端更新這個服務器恨统,另一個客戶端更新那個服務器,因此記錄哪些更新以怎樣的順序發(fā)生三妈,是非常重要的畜埋。你或許再想“給值加上時間戳,采用時間戳最新的即可”畴蒲,但是這種做法僅僅在所有節(jié)點服務器的時鐘完全同步的集群中有效由捎。Riak對此不做要求,事實上饿凛,保持時鐘同步是最為困難的狞玛,在許多情況下,甚至是不可能的涧窒。Riak的做法是:對每個鍵值事件(創(chuàng)建心肪,更新,刪除)做標記纠吴,標記包含兩項內(nèi)容:哪個客戶端更新了數(shù)據(jù)與以哪種順序更新硬鞍。在此基礎上,客戶端或者應用開發(fā)者戴已,需要決定誰在沖突中獲勝固该。如果你熟悉像git或者subversion之類的版本控制,不難發(fā)現(xiàn)本質(zhì)相同糖儡。
第四章 Hbase
4.5總結
4.5.1 HBase的優(yōu)點
Hbase中值得注意的特性包括健壯性的可伸縮架構伐坏,以及內(nèi)置版本和壓縮功能。Hbase內(nèi)置版本功能在某些情況下是強大的特性握联。在性能方面Hbase意味著可伸縮桦沉。如果你有大量的數(shù)據(jù),達到很多TB金闽,Hbase可能適合你纯露。Hbase在數(shù)據(jù)中心的機架內(nèi)或機架之間復制數(shù)據(jù)沒這樣就能優(yōu)雅而快速的處理節(jié)點失效。
4.5.2 Hbase的缺點
Hbase不能縮小代芜,5個節(jié)點是你想要的最低配置埠褪。文檔比較專業(yè),學習曲線更抖挤庇。Hbase除了行鍵之外不提供任何索引功能钞速。Hbase中數(shù)據(jù)類型都作為字節(jié)數(shù)組。
4.5.3 Hbase on CAP
Hbase肯定是CP