Document數據庫 VS 關係數據庫

Document數據庫 VS 關係數據庫

在今天這個傳說中的大數據時代有着各種各樣的數據庫:開源的,商業的,自研,基於開源系統改進的。一家大公司/大項目不用n個xxxDB,m個數據分析工具都不好意思和人打招呼。

問題是作爲一線開發人員(比如寫php的,寫java的,寫node.js的)關心的是怎麼搞定需求,早點下班回家,拿到項目獎金纔是王道。你這個工具nb,那個db有創新和我的KPI有毛關係?怎麼多快好省的完成項目纔是王道。

關係數據庫大家都比較熟悉了,基本上Mysql/Oracle佔據市場的主流;另一方面Document數據庫最近也比較火,其中代表是MongoDB和國產的SequoiaDB,FounderXMLDB等等。本文的試圖比較一下document數據庫和關係數據庫的區別,最後會根據筆者的淺薄經驗給大家一些使用的建議。

開發角度

這裏不談艱深的理論(我也寫不好),從一個碼農的使用的角度看:兩者其實差不多:
- 關係數據庫是寫一個SQL,得到一個或多個tuple。
- Document數據庫是根據專有的API,得到一個或多個XML/JSON。

有區別嗎?似乎沒啥大區別。以一個簡單的SNS用戶信息JSON API來說:
- 關係數據庫的用法是:根據用戶id從用戶基本信息表,用戶勳章表,用戶登陸表表中獲取數據;然後用getInt,getString等獲取數據,最後再用result = createJson(); result.put('name', strName)之類的拼成一個JSON返回。
- Document數據庫,通過一個API,獲取一個JSON,然後返回。

顯然Document類要方便的多。
- 什麼?你有框架/IDE生成代碼?嗯,你試過增加一項或者減少一項嗎?P.S. 靠框架/IDE混不利於漲工資。
- 什麼?你們公司按行數給工資?嗯,我能建議你換家公司嗎?

稍微提高一點層次,到數據庫設計的角度,兩者就有區別了。關係數據庫是需要建表的,create table ...,還記得數據庫考試的時候有所謂的數據庫三大範式嗎?而document數據庫是scheme-less的,也就是沒有模式的,不用在建表的時候就確定詳細的表結構。

這一輪Document數據庫勝,能少敲不少機械的代碼。

補充一下,目前的document數據庫基本上不支持Join操作。如果需要join操作請繞路。

性能角度

放google可以找到好多的測試報告,這裏就不再貼具體的性能對比了。實際上,根據筆者的經驗,在適合使用Document數據庫的情況下,Document數據庫可以100%擊敗關係數據庫;反之亦然。性能差距達到一個數量級是很容易的。

爲什麼會出現這種原因呢?下面的介紹不是很嚴謹也不是很全面:
1. 關係數據庫的一個表是要有詳細的定義的,在create table的時候,DBA和數據庫實際上是做了一個約定,DBA明確告知數據庫,每一個tuple包括多少列,每個列都是什麼類型。數據庫就按照約定盡其所能的存儲數據(行存儲或列存儲)。如果試圖修改這個約定,你只能Alter tableAlter table乾的事情每個數據庫略有差異:不過基本上都要修正表的所有數據,並鎖表。
2. Document數據庫不需要預先定義數據模式,數據庫不知道數據模式,Document存什麼,怎麼存完全由用戶決定。

基於上面兩點,在下面情況下,document數據庫會取得優勢:
1. 當數據模型變動時(比如增加一列),關係數據庫會對所有的數據調整(因爲你改變了和它的約定);而document不用,實際上document數據庫都不知道你改變了數據模型。
2. 當需要根據主鍵從多個表獲取數據時,關係數據庫的做法是JOIN;而document數據庫則可以把所有的數據放到一個document裏,省去了JOIN的開銷。比如上一節裏面寫的獲取用戶profile的API裏,關係數據庫需要N多表,而Document數據庫只需要一張表。

在下面情況下,關係數據庫會取得優勢:
1. 數據模式穩定,且較少空值的插入,刪除,更新和查詢。大部分傳統的數據庫應用場景都是這種。
2. 複雜的JOIN操作,Document數據庫基本上不支持JOIN。

這裏多說一句,MongoDB更新性能差的惡名很大程度上是MongoDb的實現問題(它居然用了一個庫級鎖,早期版本甚至是一個全局鎖)。SequoiaDB就沒有類似問題。好消息是MongoDB在3.0裏應該可以解決這個問題。

這一輪不存在勝負。

維護角度

Item 關係數據庫 Document數據庫
監控/維護工具 相對成熟一些,不用說Oracle,DB2這種大傢伙;就是Mysql,PostgreSql之類都有大量的開源工具 相對弱點, 基本上都是產品方維護,比如 MongoDB的MMS
人員招聘 有大量的認證和培訓機構存在的,在市場上還是比較容易找到資深/不那麼資深的DBA的 不好招人,相當一部分團隊都是研發人員兼任

這一輪,關係數據庫勝。

擴展性

OK,你的系統可以儲存10w數據,100w能存嗎?1000w能存嗎?1億能存嗎?。。。存下之後,檢索和插入還能達到設計指標嗎?
問題不僅僅是數據存儲,基於數據存儲的統計應用纔是最麻煩的問題,一個簡單的SQL,在小數據量上可以很快的得出結果。

Item 關係數據庫 Document數據庫
節點數量 一般也就幾個點或幾十個節點 幾十幾百個節點
成本 Oracle之類的商業數據庫一般按節點收費,成本較高 MongoDB/SDB是開源的
簡單查詢(單表查詢)是否可以很方便的擴展 商業和開源方案都有,很多公司也有自己的實現,在應用層支持也很容易 在設計上就支持, 後發優勢
複雜查詢(Join/Group By)是否可以很方便的擴展 商業產品和閉源數據庫有,開源的靠譜產品筆者還沒有發現 目前不支持Join,但是支持Group By;另外很多關係數據庫需要用Join的事兒,Document都不需要JOIN
高可用性 商業和開源方案都有 支持
分佈式事務 兩階段事務 簡單的事務支持(在事務這一塊MongoDB和SequoiaDB在2015年都有大的動作)

可以看出,Document類的數據庫(兩個典型產品MongoDB和SequoiaDB)在設計之初就考慮到了擴展性問題,再加上API的複雜程度不如SQL,所有對擴展性支持良好;而關係數據庫受SQL的複雜程度連累,除個別商業產品外,筆者沒有看到好的MPP方案,國外Amazon和國內的阿里都在搞自己的RDS。

順便吐槽一句,SQL過於複雜,以至於讓SQL語句擴展到多個節點本身就是一件讓人很痛苦的事兒。MongoDB自己設計了查詢語言,太複雜的從語言就不支持。

這一輪,Document數據庫勝。

Document適合什麼樣的場景

筆者水平有限,只能給出一些零散的提示和感悟。

什麼樣的項目適合使用Document數據庫

  1. 數據類型多且存在大量的空項。比如SNS類的用戶profile,手機,郵箱,地址,性別……有很多項,而且大部分是空項。
  2. 數據類型經常變動。還是上面SNS類的例子,如果用關係數據庫的話,產品經理可能今天加一個勳章,明天加個等級的,關係數據庫沒要每次alter table
  3. 數據類型包括多類數據項,數據類型都很多,且每個類型都很複雜。比如一個簡單的用戶行爲分析,張三買過3部手機,都是什麼手機;訂過8次房,都在什麼地方;打過127次車,最近10次都去了哪兒。用關係數據庫不是無法表示這麼複雜的場景,而是要麼建一個碩大無比的表,要麼查詢時做多表JOIN;兩者都不那麼優雅。

下面的例子是筆者在實際工作中遇到的,隱去具體的業務細節。

實例1. 某醫院開發患者電子病歷。
- 採用關係關係數據庫(Oracle)需要用幾十張表保存患者的各類數據:比如血檢一張表,肝部b超一張表,xxx檢查一張表,處方一張表等等。問題是對患者的分析是要考慮多個檢查結果和歷史處方的,使用關係數據庫往往需要n張表做JOIN,N張百萬,千萬級的表做JOIN是一件很刺激的事情。
- Doucment數據庫直接按患者id存儲各類數據。
- 採用Document數據庫後,性能大概提高了10倍,編碼量也有所減少。

實例2. 某創業公司的後臺數據統計。創業公司嘛,產品經理經常搗鼓點新功能,搞點活動啥,要看效果咋辦呢?
- 根據日誌統計嘛,用戶的行爲會在日誌裏進行記錄,比如action=function1
- 每小時/分鐘/天的數據統計都被整理到一個JSON文件中,比如2015-01-01的統計document爲{'function1':12,'function2':13}。所有數據都被保存到MongoDB當中。
- 統計後臺使用Node.js實現,可以直接從MongoDB中讀取數據,並展示各種圖表數據(趨勢圖,柱狀圖,表格)。
- 用類似於 display?interval=hour&fromTime=2day&endTime=lastDay&items='fucntion1,function2'就可以看到相應的圖表。
- 研發人員唯一需要做的是在後臺系統增加一條超級鏈接即可。懂點技術的產品經理自己加也沒問題。
- 開發成本嘛,很低。

實例3. 某大公司每天都要生成若干個複雜的報表給若干個郵件組,數據列包括c1,c2, c3 …. c100。、
- 不同郵件組需要不同的數據,比如郵件組1需要c1,c2,c4,c8…;郵件2需要c2,c3,c5,c0等等。多餘的數據項不必也不能發給多餘的郵件組(你一個屌絲工程師難道能看營收數據?)。
- 每個數據項對不同的郵件組有不同的展示方式,比如給老闆看看大概的趨勢圖就可以了,給分析師就要給具體的數字了。
- 由於管理問題,收件人又不全都是郵件組,比如某些郵件應該發個某些人,這些人還經常變動。

上述需求,用Document數據庫可以輕易實現。每個郵件組的配置保存成一個docuemnt即可,可以很方便的調整配置。使用關係數據庫不是不可以實現類似功能,數據要散落在不同的表裏,管理和使用都要多費功夫。

什麼樣的項目適合使用關係數據庫

  1. 對事務要求較高的系統,比如銀行,保險,政府之類。這類的系統強烈要求ACID,一點都不能含糊。(銀行少了筆錢或者你的保險少了一個月都是不能忍的)
  2. 已經有大量基於SQL的應用的系統。大量應用,更大量的SQL;換成其他關係數據庫都是一個不可能完成的任務,換成Document數據庫,我只能呵呵了。
  3. 比較明確簡單的需求。比如TCP的各種測試。
  4. 團隊技術水平不高,且已經熟悉關係數據庫了。這種情況下極大概率會誤用document數據庫,最終會造成災難。

兩者皆不適合的項目

  1. 真正要求高併發的數據系統,比如微博,比如百度貼吧,比如facebook,比如12306。不要指望任何現成的產品可以支撐住高併發的應用,那些系統都需要專門的架構和設計的;更不要指望什麼第三方公司可以提供整套的解決方案。
  2. 簡單而純粹的應用,比如文件服務器。Hadoop就很好;比如簡單key-value存儲或者緩存,redis/memcache就很好。

小結

總的來說,Document數據庫模型和關係數據模型都不是什麼銀彈,都無法解決全部的問題。在現階段,只能根據實際的業務場景/人員和公司現狀加以選擇。

不負責任的結論:
- key-document數據庫更適合複雜的系統。
- 關係數據庫更適合大而相對簡單的系統。
- Hadoop之類等更適合大而簡單的系統。

沒有通用的方案,雖然會帶來跟更多糾結,開發時間和加班,但是也能體現出開發人員能力,或者說要求漲工資的理由。

附 數據庫的演進

  1. 據各種小道大道消息,MongoDB/SequoiaDB都會用支持事務的數據庫引擎替換掉目前的mmap解決方案,時間點大概在2015年上半年:新版本將在內存控制和事務上會大大縮小和關係型數據庫的距離。
  2. Oracle等商業數據庫以及Postgresql/Mysql等開源數據庫都正在或打算原生的支持Json/XML。

可以看出,關係數據庫和Document數據庫的開發者都已經看到自身的不足和對方的長處。彼此追趕中。也證明了這兩種產品都被市場所需要。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章