數(shù)據(jù)模型和查詢語言 -- 關系模型與文檔模型(一)

在今天脓匿,最著名的數(shù)據(jù)模型莫過于SQL了吧在岂。這是一個Codd在1970年提出的關系模型:數(shù)據(jù)被組織成關系(稱為SQL中的表)考余,其中每個關系都是無序的元組集合(SQL中的行)杏死。

關系模型是一個理論上的設想,在當時很多人都懷疑它是否能有效地實施煌寇。然而焕蹄,到上世紀80年代中期,關系數(shù)據(jù)庫管理系統(tǒng)和SQL已經(jīng)成為大多數(shù)需要使用某種常規(guī)結構來存儲和查詢數(shù)據(jù)的人的首選工具阀溶,關系數(shù)據(jù)庫的主導地位也持續(xù)了25年之久腻脏。

關系數(shù)據(jù)庫的根源在于業(yè)務數(shù)據(jù)處理鸦泳,在20世紀60年代和70年代這些其實是在大型計算機上執(zhí)行的。而從今天的角度來看永品,用例看起來也十分普通:典型的事務處理(進入銷售或銀行事務做鹰、航空公司預訂、倉庫中的庫存)和批處理(客戶發(fā)票鼎姐、工資钾麸、報表)。當時的其他數(shù)據(jù)庫還在迫使應用程序開發(fā)人員考慮數(shù)據(jù)庫中數(shù)據(jù)的內(nèi)部表示症见,而關系模型的目標卻是在一個更干凈的接口后面隱藏實現(xiàn)細節(jié)喂走。

多年來殃饿,人們都在比較不同的數(shù)據(jù)存儲和查詢的方法谋作。比如,在20世紀70年代和80年代早期乎芳,網(wǎng)絡模型和層次模型是主要的替代方案遵蚜,但是關系模型開始主導它們。在20世紀80年代末和90年代初奈惑,對象數(shù)據(jù)庫再次出現(xiàn)吭净。而XML數(shù)據(jù)庫出現(xiàn)在21世紀初,但也只看到了特定的應用肴甸。關系模型的每個競爭對手都在其時代產(chǎn)生了大量的炒作寂殉,但從未持續(xù)過2次。

隨著計算機變得更加強大和網(wǎng)絡化原在,它們開始被用于日益多樣化的用途友扰。值得注意的是,關系數(shù)據(jù)庫在最初的業(yè)務數(shù)據(jù)處理范圍之外庶柿,開始被廣泛應用于各種用例村怪。今天在web上看到的大部分內(nèi)容仍然由關系數(shù)據(jù)庫驅(qū)動,比如在線發(fā)布浮庐、討論甚负、社交網(wǎng)絡、電子商務审残、游戲梭域、SAAS應用程序,甚至更多搅轿。

NOSQL的誕生

而現(xiàn)在碰辅,NoSQL是顛覆關系模式主導地位的最新嘗試〗槭保“NoSQL”這個名字很不幸没宾,因為它實際上并不指代任何一種特定的技術——它最初只是作為一個吸引人的Twitter標簽凌彬,用在2009年的一場關于開源分布式非關系型數(shù)據(jù)庫的meetup。然而循衰,這個術語引起了很多人的關注铲敛,并迅速在網(wǎng)絡創(chuàng)業(yè)社區(qū)和其他地方傳播開來。現(xiàn)在会钝,許多有趣的數(shù)據(jù)庫系統(tǒng)都與nosql關聯(lián)在一起伐蒋,而且它還被重新解釋為不僅僅是SQL。

采用NoSQL數(shù)據(jù)庫的背后有幾個驅(qū)動因素迁酸,主要包括:

????1.大家需要一個相比于關系數(shù)據(jù)庫來說先鱼,具有更大的可伸縮性,包括非常大的數(shù)據(jù)集或非常高的寫入吞吐量的系統(tǒng)奸鬓。

????2.相比于商業(yè)數(shù)據(jù)庫產(chǎn)品焙畔,人們當然更偏愛于免費和開源軟件

????3.一些特殊的查詢操作,這是關系模型沒有很好支持的

????4.對關系模型限制性的失望串远,以及對更動態(tài)宏多、更富表現(xiàn)力的數(shù)據(jù)模型的渴望

不同的應用程序有不同的需求,對于一個用例來說澡罚,最好的技術選擇可能與另一個用例的最佳選擇是不同的伸但。因此,在可預見的將來留搔,關系數(shù)據(jù)庫將繼續(xù)與各種非關系型數(shù)據(jù)存儲一起使用更胖。

對象-關系不匹配

在當今,大多數(shù)應用程序開發(fā)都是用面向?qū)ο蟮木幊陶Z言完成的隔显,這導致了對SQL數(shù)據(jù)模型的常見批評:如果數(shù)據(jù)存儲在關系表中却妨,應用程序代碼中的對象和表、行和列的數(shù)據(jù)庫模型之間需要一個笨拙的轉(zhuǎn)換層荣月。模型之間的脫節(jié)有時被稱為阻抗失配管呵。

像Hibernate這樣的對象-關系映射(ORM)框架減少了這個翻譯層所需的樣板代碼的數(shù)量,但是它們不能完全隱藏這兩個模型之間的差異哺窄。

例如捐下,圖2-1演示了如何在關系模式中表達簡歷(LinkedIn個人資料)。整個概要文件可以通過唯一標識符userid來標識萌业。像firstname和lastname這樣的字段在每個用戶中出現(xiàn)一次坷襟,因此它們可以被建模為用戶表中的列。然而生年,大多數(shù)人的職業(yè)生涯(職位)都不止一份工作婴程,而且人們的受教育年限和接觸信息的數(shù)量也各不相同。由此可見抱婉,這是一個一對多的關系档叔,我們也可以用不同的方式表示:

? ? 1.在傳統(tǒng)SQL模型中(SQL1999)桌粉,最常見的表達方式是將位置、教育衙四、和聯(lián)系信息存在單獨的表中铃肯,然后跟用戶表建立外鍵引用,如圖2-1所示传蹈。

? ? 2.后來的SQL標準版本增加了對結構化數(shù)據(jù)類型和XML數(shù)據(jù)的支持押逼;這使得多值數(shù)據(jù)可以被存儲在一行中,并支持在這些文檔中查詢和索引惦界。這些特性在Oracle挑格、IBM DB2、SQL Server和PostgreSQL中都得到了不同程度的支持沾歪。JSON數(shù)據(jù)類型也受到幾個數(shù)據(jù)庫的支持漂彤,包括IBM DB2、MySQL和PostgreSQL瞬逊。

? ? 3.第三種選擇是將工作显歧、教育和聯(lián)系信息轉(zhuǎn)化成JSON或XML文檔仪或,將其存儲在數(shù)據(jù)庫的文本列中确镊,并讓應用程序解釋其結構和內(nèi)容。在這種設置中范删,通常不能使用數(shù)據(jù)庫直接查詢列內(nèi)的值蕾域。


圖2-1--使用關系模式表示一個LinkedIn個人資料。

對于像簡歷這樣的數(shù)據(jù)結構來說到旦,它是一個自成體系的文檔旨巷,所以用JSON表示非常合適:參見例2-1。JSON的表達比XML要簡單得多添忘。面向文檔的數(shù)據(jù)庫采呐,如MongoDB、RethinkDB搁骑、CouchDB和Espresso斧吐,都支持這種數(shù)據(jù)模型。

例2-1仲器,將LinkedIn個人資料用一個JSON表示:

{ "user_id": 251, "first_name": "Bill", "last_name": "Gates", "summary": "Co-chair of the Bill & Melinda Gates... Active blogger.", "region_id": "us:91", "industry_id": 131, "photo_url": "/p/7/000/253/05b/308dd6e.jpg", "positions": [ {"job_title": "Co-chair", "organization": "Bill & Melinda Gates Foundation"}, {"job_title": "Co-founder, Chairman", "organization": "Microsoft"} ], "education": [ {"school_name": "Harvard University", "start": 1973, "end": 1975}, {"school_name": "Lakeside School, Seattle", "start": null, "end": null} ], "contact_info": { "blog": "http://thegatesnotes.com", "twitter": "http://twitter.com/BillGates" }}

一些開發(fā)人員認為JSON模型減少了應用程序代碼和存儲層之間的阻抗失配煤率。然而,正如我們將在第4章中看到的乏冀,JSON作為一種數(shù)據(jù)編碼格式也存在問題蝶糯。缺乏schema通常被認為是一種優(yōu)勢,我們將在后續(xù)“文檔模型的模式靈活性”中討論這一點辆沦。

與圖2-1中的多表模式相比昼捍,JSON很明顯更加適合识虚。如果您想要在關系示例中獲取profile,您需要執(zhí)行多條查詢(通過userid查詢每個表)妒茬,或者在users表及其下屬表之間的做join舷礼。在JSON表示中,所有相關的信息都在一個地方郊闯,一個查詢就足夠了妻献。

從用戶profile到用戶的位置、教育歷史和聯(lián)系信息的一對多關系团赁,我們可以看出這是數(shù)據(jù)中的樹結構育拨,而JSON能夠顯示的表達此樹結構(參見圖2-2)。


圖2-2-- 一對多關系形成的一個樹形結構

多對一和多對多關系

在前一節(jié)中欢摄,以2-1為例熬丧,區(qū)域id和行業(yè)id被作為id,而不是純文本字符串“大西雅圖地區(qū)”和“慈善”怀挠。為什么析蝴?

如果用戶界面有用于輸入?yún)^(qū)域和行業(yè)字段的文本框,那么將它們存儲為純文本字符串是有意義的绿淋。但是闷畸,擁有一個標準化的地理區(qū)域和行業(yè)列表,并讓用戶從下拉列表或自動完成列表中進行選擇是有一定的優(yōu)勢的吞滞,具體如下:

? ? 1.一致的風格和拼寫

? ? 2.避免模棱兩可(例如佑菩,如果有幾個同名的城市)

? ? 3.易于更新——名稱只存儲在一個地方,因此裁赠,如果需要更改的話殿漠,它很容易進行更新(例如,由于政治事件而更改城市名稱)佩捞。

????4.本地化支持——當站點被翻譯成其他語言時绞幌,標準化的列表可以本地化,因此區(qū)域和行業(yè)可以瀏覽者的本地語言來顯示一忱。

? ? 5.更好的搜索莲蜘。

是否存儲ID或文本字符串是一個關于重復的問題。當您使用一個ID時掀潮,對人類有意義的信息(例如慈善這個詞)只存儲在一個地方菇夸,并且所有引用它的信息都使用一個ID(它只在數(shù)據(jù)庫中有意義)。當您直接存儲文本時仪吧,您將在使用它的每條記錄中復制有意義的信息庄新。

使用ID的優(yōu)點是,由于它對人沒有意義,所以它永遠不需要改變:ID可以保持不變择诈,即使它標識的信息發(fā)生了變化械蹋。任何對人類有意義的事情都需要在將來的某個時候改變——如果這些信息是重復的,那么所有多余的副本都需要更新羞芍。這就會導致寫管理費用哗戈,并存在不一致的風險(一些信息的副本會被更新,而其他的則不會)荷科。消除這種重復是數(shù)據(jù)庫中標準化背后的關鍵思想唯咬。

不幸的是,規(guī)范化這種數(shù)據(jù)需要多對一關系(許多人生活在一個特定的區(qū)域畏浆,許多人在一個特定的行業(yè)工作)胆胰,這與文檔模型不太匹配。在關系型數(shù)據(jù)庫中刻获,用ID引用其他表中的行是很正常的蜀涨,因為join很容易。在文檔數(shù)據(jù)庫中蝎毡,通常不需要對一對多的樹結構進行join厚柳,而且對join的支持常常是弱的。

如果數(shù)據(jù)庫本身不支持join沐兵,那么您必須通過對數(shù)據(jù)庫進行多次查詢來模擬應用程序代碼中的join别垮。(在這種情況下,區(qū)域和行業(yè)的列表可能很小痒筒,而且變化很慢宰闰,因此應用程序可以簡單地將它們保存在內(nèi)存中茬贵。但是簿透,創(chuàng)建join的工作從數(shù)據(jù)庫轉(zhuǎn)移到應用程序代碼。)

此外解藻,即使應用程序的初始版本很適合 join-free的文檔模型老充,數(shù)據(jù)也會隨著特性被添加到應用程序中而變得更加相互關聯(lián)。例如螟左,考慮一下我們可以對簡歷示例進行一些更改:

組織和學校作為實體

在前面的描述中啡浊,組織(用戶工作的公司)和學校名稱(他們學習的地方)只是字符串。也許它們應該是對實體的引用胶背?然后巷嚣,每個組織、學星鳎或大學都可以擁有自己的網(wǎng)頁(帶有徽標廷粒、新聞提要等);每個簡歷都可以鏈接到它提到的組織和學校,并包含他們的標志和其他信息(見圖2-3坝茎,來自LinkedIn的一個例子)涤姊。

建議

假設您想要添加一個新特性:一個用戶可以為另一個用戶寫推薦信。這些建議在被推薦的用戶的簡歷上顯示嗤放,并附上推薦用戶的姓名和照片思喊。如果推薦者更新他們的照片,他們所寫的任何推薦都需要反映新照片次酌。因此恨课,這些建議應該有一個針對作者的個人資料的引用。


圖2-3--公司名稱不只是一個字符串岳服,而是一個公司實體的鏈接? ?

圖2-4說明了這些新特性為什么需要多對多關系庄呈。每個點狀矩形中的數(shù)據(jù)可以被分組到一個文檔中,但是對組織派阱、學校和其他用戶的引用需要被表示為引用诬留,并且在查詢時需要join。


圖2 - 4--多對多關系的擴展簡歷??
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贫母,一起剝皮案震驚了整個濱河市文兑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌腺劣,老刑警劉巖绿贞,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異橘原,居然都是意外死亡籍铁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門趾断,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拒名,“玉大人,你說我怎么就攤上這事芋酌≡鱿裕” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵脐帝,是天一觀的道長同云。 經(jīng)常有香客問我,道長堵腹,這世上最難降的妖魔是什么炸站? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮疚顷,結果婚禮上旱易,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好咒唆,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布届垫。 她就那樣靜靜地躺著,像睡著了一般全释。 火紅的嫁衣襯著肌膚如雪装处。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天浸船,我揣著相機與錄音妄迁,去河邊找鬼。 笑死李命,一個胖子當著我的面吹牛登淘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播封字,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼黔州,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了阔籽?” 一聲冷哼從身側(cè)響起流妻,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎笆制,沒想到半個月后绅这,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡在辆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年证薇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匆篓。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡浑度,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出奕删,到底是詐尸還是另有隱情俺泣,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布完残,位于F島的核電站,受9級特大地震影響横漏,放射性物質(zhì)發(fā)生泄漏谨设。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一缎浇、第九天 我趴在偏房一處隱蔽的房頂上張望扎拣。 院中可真熱鬧,春花似錦、人聲如沸二蓝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刊愚。三九已至踊跟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸥诽,已是汗流浹背商玫。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留牡借,地道東北人拳昌。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像钠龙,于是被迫代替她去往敵國和親炬藤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容