創(chuàng)新的背后往往會(huì)刺激痛苦。這一點(diǎn)在PDD(我們親切地稱為痛處驅(qū)動(dòng)開發(fā))軟件開發(fā)領(lǐng)域尤為真實(shí)。從上世紀(jì)80年代以來(lái),我們就都知道如何處理關(guān)系型數(shù)據(jù)——只要把數(shù)據(jù)放到關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(RDBMS)中,就可以使用SQL語(yǔ)句操作數(shù)據(jù)。然而,在過(guò)去幾年來(lái),我們的行業(yè)采納NoSQL數(shù)據(jù)庫(kù)的趨勢(shì)在增長(zhǎng),數(shù)據(jù)不見(jiàn)得都在關(guān)系型數(shù)據(jù)庫(kù)中存儲(chǔ)了。
誠(chéng)然,在互聯(lián)網(wǎng)上有成千上萬(wàn)關(guān)于選擇SQL還是NoSQL的辯論。但是,這兩者是不是必須站在對(duì)立面戰(zhàn)斗呢?如果你選擇一種或另一種,你知道為什么做選擇,知道各自有何潛在益處嗎?本文簡(jiǎn)要地討論了SQL和NoSQL兩種方法最常見(jiàn)的優(yōu)點(diǎn)和缺點(diǎn),包括簡(jiǎn)單的比較和開發(fā)者考慮的因素。像別的一些話題一樣,這個(gè)問(wèn)題沒(méi)有對(duì)錯(cuò),永遠(yuǎn)正確的經(jīng)典答案依然是:具體問(wèn)題具體分析。
數(shù)據(jù)表VS.數(shù)據(jù)集
關(guān)系型和非關(guān)系型數(shù)據(jù)庫(kù)的主要差異是數(shù)據(jù)存儲(chǔ)的方式。關(guān)系型數(shù)據(jù)天然就是表格式的,因此存儲(chǔ)在數(shù)據(jù)表的行和列中。數(shù)據(jù)表可以彼此關(guān)聯(lián)協(xié)作存儲(chǔ),也很容易提取數(shù)據(jù)。與其相反,非關(guān)系型數(shù)據(jù)不適合存儲(chǔ)在數(shù)據(jù)表的行和列中,而是大塊組合在一起。非關(guān)系型數(shù)據(jù)通常存儲(chǔ)在數(shù)據(jù)集中,就像文檔、鍵值對(duì)或者圖結(jié)構(gòu)。你的數(shù)據(jù)及其特性是選擇數(shù)據(jù)存儲(chǔ)和提取方式的首要影響因素。
預(yù)定義結(jié)構(gòu)VS.動(dòng)態(tài)結(jié)構(gòu)
關(guān)系型數(shù)據(jù)通常對(duì)應(yīng)于結(jié)構(gòu)化數(shù)據(jù),因?yàn)閿?shù)據(jù)表都有預(yù)定義好的結(jié)構(gòu)(列的定義),結(jié)構(gòu)描述了數(shù)據(jù)的形式和內(nèi)容。這一點(diǎn)對(duì)數(shù)據(jù)建模至關(guān)重要,你必須“第一時(shí)間先把結(jié)構(gòu)定義好”。雖然預(yù)定義結(jié)構(gòu)帶來(lái)了可靠性和穩(wěn)定性,但是已經(jīng)存入數(shù)據(jù)的表結(jié)構(gòu)要修改就非常痛苦了。另一方面,非關(guān)系型數(shù)據(jù)基于動(dòng)態(tài)結(jié)構(gòu),通常適用于非結(jié)構(gòu)化數(shù)據(jù)。非關(guān)系型數(shù)據(jù)可以很容易適應(yīng)數(shù)據(jù)類型和結(jié)構(gòu)的變化,因?yàn)閯?dòng)態(tài)結(jié)構(gòu)本身就支持這一點(diǎn)。
存儲(chǔ)規(guī)范化VS存儲(chǔ)代價(jià)
關(guān)系型數(shù)據(jù)庫(kù)的數(shù)據(jù)存儲(chǔ)是為了更高的規(guī)范性,把數(shù)據(jù)分隔成最小的邏輯表(關(guān)系表)以避免重復(fù),獲得最精簡(jiǎn)的空間利用。雖然數(shù)據(jù)規(guī)范性會(huì)使數(shù)據(jù)管理更清晰,但它通常也會(huì)帶來(lái)一點(diǎn)點(diǎn)復(fù)雜性,尤其是單個(gè)操作可能涉及多個(gè)關(guān)系表的時(shí)候,數(shù)據(jù)管理就有點(diǎn)麻煩。另外,更精簡(jiǎn)的空間利用通??梢怨?jié)約寶貴的數(shù)據(jù)存儲(chǔ),但是在當(dāng)今世界我們基本可以認(rèn)為存儲(chǔ)的代價(jià)(磁盤空間)是微不足道的。而非關(guān)系型數(shù)據(jù)存儲(chǔ)在平面數(shù)據(jù)集中,數(shù)據(jù)經(jīng)??赡艽嬖谥貜?fù)。單個(gè)數(shù)據(jù)庫(kù)很少被分隔開,而是存儲(chǔ)成一個(gè)整體,這樣是為了整塊數(shù)據(jù)更容易讀寫。
縱向擴(kuò)容VS橫向擴(kuò)容
SQL和NoSQL數(shù)據(jù)庫(kù)最大的差別可能是在擴(kuò)展方式上,要支持日益增長(zhǎng)的需求當(dāng)然要擴(kuò)展。要支持更多并發(fā)量,SQL數(shù)據(jù)庫(kù)是縱向擴(kuò)展,也就是說(shuō)提高處理能力,使用速度更快速的計(jì)算機(jī),這樣處理相同的數(shù)據(jù)集就更快了。因?yàn)閿?shù)據(jù)存儲(chǔ)在關(guān)系表中,操作的性能瓶頸可能涉及很多個(gè)表,這都需要通過(guò)提高計(jì)算機(jī)性能來(lái)客服。雖然SQL數(shù)據(jù)庫(kù)有很大擴(kuò)展空間,但最終肯定會(huì)達(dá)到縱向擴(kuò)展的上限。而NoSQL數(shù)據(jù)庫(kù)是橫向擴(kuò)展的。非關(guān)系型數(shù)據(jù)存儲(chǔ)天然就是分布式的,NoSQL數(shù)據(jù)庫(kù)的擴(kuò)展可以通過(guò)給資源池添加更多普通的數(shù)據(jù)庫(kù)服務(wù)器(節(jié)點(diǎn))來(lái)分擔(dān)負(fù)載。
結(jié)構(gòu)化查詢VS非結(jié)構(gòu)化查詢
關(guān)系型數(shù)據(jù)庫(kù)通過(guò)所謂結(jié)構(gòu)化查詢語(yǔ)言(也就是我們常說(shuō)的SQL)來(lái)操作數(shù)據(jù)。SQL支持?jǐn)?shù)據(jù)庫(kù)CRUD(增加,查詢,更新,刪除)操作的功能非常強(qiáng)大,是業(yè)界標(biāo)準(zhǔn)用法。非關(guān)系型數(shù)據(jù)庫(kù)以塊(像文檔一樣)為單元操縱數(shù)據(jù),使用所謂的非結(jié)構(gòu)化查詢語(yǔ)言(UnQL),它是沒(méi)有標(biāo)準(zhǔn)的,因數(shù)據(jù)庫(kù)提供商的不同而不同。關(guān)系型表中主鍵的概念對(duì)應(yīng)非關(guān)系存儲(chǔ)中的文檔Id。SQL數(shù)據(jù)庫(kù)使用預(yù)定義優(yōu)化方式(比如列索引定義)幫助加速查詢操作,而NoSQL數(shù)據(jù)庫(kù)采用更簡(jiǎn)單而精確的數(shù)據(jù)訪問(wèn)模式。
映射VS本地化
SQL和NoSQL數(shù)據(jù)存儲(chǔ)的選擇還取決于開發(fā)人員,盡管這個(gè)因素影響不大。采用面向?qū)ο缶幊陶Z(yǔ)言的開發(fā)人員通常會(huì)同時(shí)操作一個(gè)或多個(gè)數(shù)據(jù)實(shí)體(包括嵌套數(shù)據(jù)、列表和數(shù)組的復(fù)雜結(jié)構(gòu)),把數(shù)據(jù)傳遞給應(yīng)用程序用戶界面。要是討論到底層數(shù)據(jù)庫(kù),事情就并不總是那么公平合理了。在關(guān)系型存儲(chǔ)中,數(shù)據(jù)實(shí)體通常需要分成多個(gè)部分進(jìn)行規(guī)范化,然后分開存儲(chǔ)到多個(gè)關(guān)系型表中精簡(jiǎn)存儲(chǔ)。幸運(yùn)的是,這是一個(gè)長(zhǎng)期存在的問(wèn)題,大部分編程平臺(tái)都有相應(yīng)的簡(jiǎn)單解決方案,比如ORM層(對(duì)象關(guān)系映射)。ORM是位于關(guān)系型數(shù)據(jù)源和開發(fā)者使用的面向?qū)ο髷?shù)據(jù)實(shí)體之間的一個(gè)映射層。然而,對(duì)于非關(guān)系型存儲(chǔ),不需要規(guī)范化數(shù)據(jù),復(fù)雜數(shù)據(jù)實(shí)體可以整體存放在獨(dú)立單元中。應(yīng)用程序中使用的對(duì)象通常序列化為JSon串,存儲(chǔ)在NoSQL數(shù)據(jù)庫(kù)的JSon文檔中。
事務(wù)性VS純擴(kuò)展性
如果你的數(shù)據(jù)操作需要高事務(wù)性或者復(fù)雜數(shù)據(jù)查詢需要控制執(zhí)行計(jì)劃,那么傳統(tǒng)的SQL數(shù)據(jù)庫(kù)從性能和穩(wěn)定性方面考慮是你的最佳選擇。SQL數(shù)據(jù)庫(kù)支持對(duì)事務(wù)原子性細(xì)粒度控制,并且易于回滾事務(wù)。雖然NoSQL數(shù)據(jù)庫(kù)也可以使用事務(wù)操作,但它們真正閃亮的價(jià)值是在操作的擴(kuò)展性和大數(shù)據(jù)量處理方面。
ACID VS CAP
SQL 數(shù)據(jù)庫(kù)久負(fù)盛名的價(jià)值就是通過(guò)所謂的ACID屬性(原子性,一致性,隔離性,持久性)保證數(shù)據(jù)完整性,大部分關(guān)系型存儲(chǔ)供應(yīng)商都支持ACID。我們的目標(biāo)是支持隔離不可分割的事務(wù),其變化是持久的,數(shù)據(jù)也保持一致狀態(tài)。而NoSQL數(shù)據(jù)庫(kù)是讓你在CAP(一致性,可用性,分區(qū)容忍度)中的任意兩項(xiàng)中選擇,因?yàn)樵诨诠?jié)點(diǎn)的分布式系統(tǒng)中,很難做到三項(xiàng)都滿足。
數(shù)據(jù)VS大數(shù)據(jù)
SQL數(shù)據(jù)庫(kù)可以可靠地存儲(chǔ)和處理數(shù)據(jù),而NoSQL最大的優(yōu)勢(shì)是在應(yīng)對(duì)大數(shù)據(jù)方面,也就是由我們社會(huì)或者計(jì)算機(jī)每天產(chǎn)生的大量非結(jié)構(gòu)化的數(shù)據(jù)實(shí)體。NoSQL用無(wú)模式方式做數(shù)據(jù)管理,所以其橫向擴(kuò)展?jié)摿κ菬o(wú)限的,這可能是深度處理大數(shù)據(jù)捕獲、管理、檢索、分析和可視化的唯一有效途徑。
數(shù)據(jù)記錄VS物聯(lián)網(wǎng)和人聯(lián)網(wǎng)
關(guān)系數(shù)據(jù)庫(kù)在關(guān)注數(shù)據(jù)規(guī)范化和保證性能的基礎(chǔ)上精簡(jiǎn)存儲(chǔ)。但是近年來(lái),我們產(chǎn)生數(shù)據(jù)的速度遠(yuǎn)大于關(guān)系型存儲(chǔ)能滿足存儲(chǔ)的能力增長(zhǎng)。刺激數(shù)據(jù)如此迅猛增長(zhǎng)的原因是:巨大量的用戶數(shù)和物聯(lián)網(wǎng)。連接到互聯(lián)網(wǎng)的用戶在成倍增加,在同步使用我們的應(yīng)用。由于大量移動(dòng)設(shè)備數(shù)據(jù)傳感設(shè)備接入互聯(lián)網(wǎng),機(jī)器產(chǎn)生的數(shù)據(jù)量也大幅增加。因此企業(yè)必須尋求NoSQL技術(shù)及基礎(chǔ)架構(gòu)來(lái)處理持續(xù)涌入的半結(jié)構(gòu)化和非結(jié)構(gòu)化數(shù)據(jù)。
內(nèi)部部署VS云計(jì)算
云計(jì)算現(xiàn)在已經(jīng)無(wú)處不在了,它兼具SQL和NoSQL數(shù)據(jù)庫(kù)的益處。云環(huán)境中的關(guān)系型存儲(chǔ)通常是以服務(wù)形式提供的,是可復(fù)制、高可用性且分布式的,極大地提高了橫向擴(kuò)展能力。托管于云服務(wù)中的NoSQL數(shù)據(jù)庫(kù)也天然享有自動(dòng)分片的好處,可以階段性地靈活彈性處理,集成高速緩存和巨大的計(jì)算能力來(lái)捕獲、存儲(chǔ)和分析大數(shù)據(jù)。
付費(fèi)VS開源
有一種看法認(rèn)為,SQL數(shù)據(jù)庫(kù)大多數(shù)比較昂貴,而NoSQL數(shù)據(jù)庫(kù)通常都是開源的。事實(shí)上,兩種類型數(shù)據(jù)庫(kù)都有開源的和商業(yè)的。常見(jiàn)的SQL 數(shù)據(jù)庫(kù)有微軟公司的SQL Server,MySQL,SQLite,Oracle和PostGres。流行的NoSQL數(shù)據(jù)庫(kù)有Couchbase,MongoDB,Redis,BigTable和RavenDB。
結(jié)論
就像Neo之于Matrix,你可以選擇。幸福的無(wú)知和幻想或者接受殘酷的現(xiàn)實(shí)。但是,盲目選擇使用SQL還是NoSQL技術(shù),或者根據(jù)大眾需求選擇都是在幻想有魔法會(huì)自動(dòng)選擇合適的方案。SQL和NoSQL這兩者都有各自的優(yōu)缺點(diǎn),選擇正確的架構(gòu)取決于你構(gòu)建應(yīng)用的需求。傳統(tǒng)SQL數(shù)據(jù)庫(kù)依然非常強(qiáng)大,可以可靠地處理你的事務(wù)性需求并保持完整性。只有在你接近關(guān)系數(shù)據(jù)庫(kù)局限性邊緣時(shí),或者你的數(shù)據(jù)處理量浩如煙海時(shí),操作擴(kuò)展需要更加分布式的系統(tǒng)時(shí),才考慮NoSQL方案??紤]這些因素之后再做選擇,你就可以變成釋放你的數(shù)據(jù)構(gòu)建下一代應(yīng)用令人嘆為觀止的神人。