作为近年最为火热的文档型数据库,mongodb受到了越来越多人的关注,但是由于国内的mongodb相关技术分享屈指可数,不少朋友都在抱怨无从下手。本期周李洋为大家分享面对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中文站博主
<b></b>
<b>本文来自云栖社区合作伙伴"dbaplus",原文发布时间:2016-01-15</b>