面對Schema free的MongoDB,如何規范你的schema
作為近年最為火熱的文檔型數據庫,MongoDB受到了越來越多人的關注,但是由于國內的MongoDB相關技術分享屈指可數,不少朋友都在抱怨無從下手。本期【DBA+社群】聯合發起人周李洋為大家分享面對Schema free 的MongoDB時,如何規范你的schema。將從實際應用的角度,并覆蓋調優,troubleshooting等方面來進行MongoDB的干貨分享,希望能對大家帶來幫助。
目錄:
-
MongoDB文檔模型帶來的好處
-
Variety
-
我們為什么要用Variety呢?
-
Document Validation
-
validation的限制
如果希望了解更多MongoDB基礎的信息,還請大家Google下。我們知道MongoDB是一個文檔型數據庫,scheme free 是其非常重要的特性,但是在生產中我們應該怎么如合理利用這個特性,合理處理MongoDB的schema呢?
一、MongoDB文檔模型帶來的好處
大家都知道MongoDB是文檔型數據庫,是Schema Free的。 那么MongoDB的文檔模型能給我們帶來哪些好處呢,在這簡單列舉幾個:
1、json形式
在MongoDB中,開發人員可以直接將一個json數據存儲進MongoDB,這對于開發人員來說是非常友好額;
2、讀寫性能高
在關系型數據庫中,我們經常會進行join、子查詢等關聯性需求,這時候往往會帶來較多的隨機IO,而在MongoDB中,我們可以通過合理的數據模型設計來將很多的關聯需求通過內嵌、反范式的方式實現,減少了隨機IO;
3、schema free
MongoDB的數據模型是靈活的,無需為了Online DDL而操心,不同的document也可以有不同的結構。
在這,我們不深入探究如何對于MongoDB 的Schema進行設計、建模,有關這部分內容,推薦大家可以閱讀TJ在開源中國的年終盛典會上分享《MongoDB 進階模式設計》,以及《Retail Reference Architecture Part 1 to 4 》。
在此我們將主要針對進行了初步建模、并正式上線服務后的schema進行巡檢與檢測的方式來進行討論。
二、Variety
Variety是一個開源的,非常使用的,檢測mongodb表字段類型、分布的一個開源工具。 正如其github readme中第一句所說"**Meet Variety, a Schema Analyzer for MongoDB**"。
Variety能夠幫助我們檢測我們MongoDB表中的字段類型、分布,并生產報表,可以讓我們非常直觀的對現有表結構、字段類型進行分析,并找出數據模型中的隱患。
下面我們通過例子來進行講解:
首先,建立一個表
我們來看看通過variety獲得的結果
test是我們的db名,users是表名。我們可以看到,針對我們之前插入的5條數據,variety跑出的結果是:
所有的document都含有_id,和name字段,60%的document含有bio字段,40%的document含有birthday和pets字段,且pets字段有2個類型的數據(4個array的,1個string的),20%的document含有someBinData和SomeWeirdLegacyKey字段。
然而生產環境中由于我們的數據量較大,比如一個表有10億條數據,全部進行掃描會耗時較長,可能我們僅希望對1000條數據進行分析,這時候就可以使用limit來限定。
由于MongoDB的可以通過內嵌來減少聯合查詢的需求,可以通過反范式來減少隨機IO,所以很可能會有嵌套出現在我們的document中。有的時候嵌套的層數太多了,影響我們的統計信息,怎么辦,我們可以通過maxDepth來限制。請參考下面的例子:
又或者我們希望指定統計的條件,比如希望caredAbout為true的,可以這樣做:
```
$ mongo test --eval "var collection = 'users', query = {'caredAbout':true}" variety.js
```
又或者是希望進行排序:
```
$ mongo test --eval "var collection = 'users', sort = { updated_at : -1 }" variety.js
```
同時我們也可以指定分析結果的format:
```
$ mongo test --quiet --eval "var collection = 'users', outputFormat='json'" variety.js
```
一般在生產中, 我們不會在primary上進行分析, 我們可以在一個priority為0,且為hidden的secondary上進行分析,這時候需要指定slaveOK:
```
$ mongo secondary.replicaset.member:31337/somedb --eval "var collection = 'users', slaveOk = true" variety.js
```
又或者說我們希望將分析結果存在mongo中:
```
$ mongo test --quiet --eval "var collection = 'users', persistResults=true" variety.js
```
并且指定存儲的詳細信息:
- resultsDatabase 分析結果所存儲的db名
- resultsCollection 分析結果所存儲的collection名
- resultsUser 分析結果存儲的實例的user
- resultsPass 分析結果所存儲的實例的password
```
mongo test --quiet --eval "var collection = 'users', persistResults=true, resultsDatabase='db.example.com/variety' variety.js
```
三、我們為什么要用Variety呢?
盡管我們MongoDB是Schema Free的,但是絕大多數情況下, 我們都希望字段類型統一。
不一致的字段類型可能會為我們的數據帶來誤差,試想一下,如果某個字段的字段類型不統一,而我們卻不知情,這時候很可能會發現業務查詢有數據丟失,數據不準確。
并且在生產環境中,應用的版本在不斷迭代,需求不斷增多,字段也隨之變化,如果在沒有規范化的上線流程檢查過后,數據庫中可能還會存在部分數據的字段確實,比如有的document有a字段,有的卻沒有,variety也可以幫助我們發現這些問題。
四、Document Validation
MongoDB 3.2推出了很多給力的功能,在這不得不提及Document Validation,Document Validation的出現我想也是MongoDB官方想表達”schema free but you may need some rules”吧,哈哈,純屬臆測。
簡單介紹下Document Validation:
我們可以為我們schema free的mongodb collection做一些限制。當然這并不是意味著MongoDB變成了關系型數據庫,個人覺得這反而更好的突出了MongoDB Schema free的特性。在正確的地方、需要的地方schema free,在適當的地方要有限制。
假設我們要新建一個表contacts,要有如下約束:
phone字段為string類型或者email字段要匹配”@mongodb.com”結尾,或者status為”Unknown”或者"Incomplete"
對已經建立了的表,我們可以通過如下方式來做限定:
這里可以看到,多了一個validationLevel參數,我們可以在設置validation的時候指定我們的validationLevel級別:
- 默認級別是strict,對該collection已有的和以后新增的document都進行validation驗證;
- 可以設置為moderate,僅對已經存在的document進行validation限定;
同時還有validationAction參數來指定當有不符合validation規則的數據進行update或者insert的時候, 我們mongodb實例如何進行處理。
- 默認級別為error,mongodb將拒絕這些不符合validation規則的insert和update。
- 可以設置為warn,mongodb會在日志中記錄,但是允許這類insert和update操作。日志中如:
五、validation的限制
- validation不能對admin、local和config庫中的collection進行設置;
- 不能對system.*這類collections進行validation設置;
作者介紹: 周李洋
-
【DBA+社群】聯合發起人
-
社區常用ID eshujiushiwo, Teambition運維總監
-
MongoDB Contribution Award獲得者, 大陸首位MongoDB Certified Professional
-
MongoDB上海用戶組發起人
-
CSDN MongoDB版主。 關注Mysql與MongoDB技術,數據架構,服務器架構,高效運維等。
-
mongo-mopre,mongo-mload作者
-
MongoDB官方翻譯組核心成員,MongoDB中文站博主
小編精心為大家挑選了近日最受歡迎的幾篇熱文:
回復 001 ,看楊志洪《【職場心路】一個老DBA的自白》;
回復 002 ,看丁俊的《【重磅干貨】看了此文,O racle SQL優化文章不必再看!》;
回復 003 ,看胡怡文《PG,一道橫跨oltp到olap的夢想之橋》;
回復 004 ,看 陳科《memcached&redis等分布式緩存的實現原理》 ;
回復 005 ,看 鄒德裕 《數據庫運維工具化:一切從“簡”,只為DBA更輕松》 ;
回復 006 ,看 鄭曉輝《存儲和數據庫不得不說的故事》 ;
回復 007 ,看 袁偉翔 《揭秘Oracle數據庫truncate原理》;
回復 008 ,看楊建榮 《立等可取:工具定制讓Oracle優化變得更簡單快捷》;
回復 009 ,看丁啟良《LINUX類主機JAVA應用程序占用CPU、內存過高分析手段》;
回復 010 ,看 徐桂林《以應用為中心的企業混合云管理》 。
DBA+社群是中國最大的涵蓋各種架構師、數據庫、中間件的微信社群! 線上分享2次/周、線下沙龍1次/月,頂級峰會6次/年,直接受眾10000+,間接影響50萬+ITer。DBA+社群致力于搭建一個學習交流、專業人脈、跨界合作的公益平臺,更多精彩請持續關注dbaplus微信訂閱號!
掃碼關注
DBAplus社群
超越DBA圈子,連接的不僅僅是DBA