MongoDB Data Models 数据结构设计
1 数据建模介绍
MongoDB的数据结构非常灵活,不强制要求数据结构.可是通常一个集合内部使用同样的结构.
数据建模的关键是平衡应用的需求和数据库运行和数据检索模型的性能.设计数据模型时,要考虑数据的使用情况和数据自身的结构
1.1 文档结构
设计MongoDB应用的数据模型的关键在于文档结构和应用程序怎样表示数据之间的关系,这有两种工具同意应用程序来表示这些关系:引用和嵌入型文档.
1.1.1 引用:
类似关系型数据库中的外键的引用,通常不同的集合中互相引用_id字段
1.1.2 内嵌数据:
某个字段的值为BSON或者某个字段值为数组,数组中的每一个值为BSON
1.2 写操作的原子性
MongoDB在文档级别的写操作是原子性的,没有不论什么单个改动多条文档,或者多个集合的操作是原子性的.包括嵌入型数据的非标准化数据将其所表示的实体的全部的相关数据在单个文档中保存,这使得对这个实体的操作变为对这个文档的原子性操作.标准化数据的过程将数据跨多个集合存储,这使得每次对实体的改动须要多次写操作,而且多次写操作不是原子性的.
然而,方便原子操作的结构或许会限制应用程序使用数据或者限制改动应用程序.
1.3 文档增长
一些更新操作,比方向数组中追加元素或者向文档中加入字段,都会导致文档大小添加.
假设文档大小超过了分配给它的空间,MongoDB将又一次在硬盘上为其分配空间.这样的增长将影响你选择使用标准化数据还是非标准化数据
1.4 数据的使用和性能
当设计数据模型的时候,考虑应用程序将如何使用你的数据库.比方说:假设你的应用程序仅仅是使用近期插入的文档,考虑使用Capped Collections,或者你的应用程序主要是读取操作,为经常使用的查询加入索引来改善性能.
2 数据建模概念
2.1 数据模型设计
高效的数据模型迎合应用程序的需求.文档结构考虑的关键因素是使用嵌入型文档还是使用引用
2.1.1嵌入型数据模型
嵌入型文档同意一个文档中保存多条相关信息应用程序能够运行更少的查询和更新操作.
下面情况使用嵌入型文档:
1.实体间有"包括"的关系
2.实体间有一对多的关系.在这样的关系中,多的一方总是在一的一方作为上下文或者作为父文档的时候出现.
嵌入型文档读操作性能较好,单一数据库的时候检索数据快.update相关数据的操作是原子性的.
缺点:嵌入型文档导致文档创建后大小的增长.进一步说,文档必须小于BSON文档的最大值限制
与嵌入型文档进行交互,须要使用"."操作符来訪问嵌入型文档
2.1.2标准化数据模型
标准化数据使用引用来描写叙述文档间的关系
下面情况使用标准化数据模型:
1.嵌入型文档模型导致数据反复的同一时候,查询性能优势不能弥补数据反复带来的不足的时候
2.用以表示更加复杂的多对多的关系
3.用以建模多层的数据集
引用比嵌入更加灵活.然而随之而来的是应用程序须要查询并解析相关的引用.换句话说,标准化数据模型会导致程序和MongoDB之间很多其它的通信.
2.2 操作的因素和数据模型
须要权衡考虑数据自身和数据库.
2.2.1 文档增长
数组的push操作,和添加新的 字段将会导致文档大小的增长.超过文档已分配的空间大小的时候,MongoDB将会为其又一次分配空间,这将导致比原地更新花费很多其它的时间,同一时候也会导致碎片化存储.尽管MongoDB自己主动会在文档之间加入空隙以降低类似的又一次分配,建立模型的时候须要尽可能的避免文档增长
2.2.2 原子操作
上面已有介绍,略
2.2.3 Sharding
MongoDB使用Sharding技术来提供水平的缩放.这些集群支持大数据集的开发和高吞吐量的操作.Sharding同意用户将一个数据库内的一个集合,通过mongod的实例或者shards的标号,分散到多个集合文档中
2.2.4 索引
使用索引来改善查询性能.在某些字段上建立索引,一般是在这些字段上的查询返回排序的结果的时候.MongoDB自己主动在_id字段上建立索引.
建立索引时要考虑下面内容:
1.每一个索引须要至少8KB的空间
2.建立索引会对写操作有负面影响,对于写操作非常多的集合来说,索引的所花费的代价非常高由于每次插入的操作都必须更新全部的索引
3.对于读操作较多的集合来说,索引一般是故意的.索引不影响没有建立索引的读操作.
4.当激活的时候,每一个索引都会消耗硬盘和内存空间.这些开销对于容量计划,特别是超过工作集的大小的考虑,是极为关键的,应该追踪的.
2.2.5 大量的集合
在某些情况下,须要选择将相关的信息存储字多个集合中而不是一个集合中,比方不同的log内容存储在不同的log集合中
通常大量的集合没有性能的减弱而是性能的优化.不同的集合对于高吞吐量的批处理进程是很重要的.
当使用有大量集合的数据模型的时候,考虑下面内容:
1.每一个集合至少须要即k空间
2.每一个索引,包含_id上的索引,须要至少8KB空间
3.对于数据库来说,一个,命名空间文件存储着该数据库全部的元数据,每一个索引和集合在这个命名空间文件里有其自己的入口.
4.MongoDB对于命名空间的数量有限制.你或许想知道当前的命名空间数,以决定数据库还能够支持多少额外的 命名空间,查询当前命名空间的数量,在mongo的shell中执行:db.system.namespaces.count()
2.2.6 数据生命周期管理
数据建模的时候应该考虑数据的生命周期管理.
假设你的应用程序须要使用限定时间段内的数据,考虑使用TTL属性.
另外,假设你的应用程序只使用近期插入的文档,考虑使用Capped Collections.它提供了对于文档的FIFO(也就是队列式)的管理,有效的支持哪些依赖于插入顺序的插入和读取操作.
2.3 GridFS
GridFS是对于超过BSON文档限制大小16M的文档存储和检索的规范.
不是将文件存储在单个文档中,GridFS将文件切割为多个部分,或者数据库,将每一个数据块作为单独的文档进行存储.默认的GridFS限制数据块大小为255k.GridFS使用两个集合来存储文件.一个结合存储文件的数据块,还有一个存储文件的元数据信息.
当你查询GridFS存储的文件的时候,驱动,或者client将又一次组装你须要的数据块.你能够对存储在GridFS中的文件运行多种查询.你也能够获取文件的某一块的信息,这使得你能够跳到视频或者音频的中间部分.
GridFS不只对于存储大小超过16M的文件实用,它能够用于存储不论什么你在訪问时不想将整个文件载入到内存中的文件