最近因为公司需求,需要用到MongoDB非关系型数据库,所以对此展开调研,并做些记录
什么是MongoDB ?
MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统,在高负载的情况下,添加更多的节点,可以保证服务器性能、MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB 将数据存储为**文档模型**,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
MongoDB 使用场景
更高的写入负载 默认情况下,MongoDB更侧重高数据写入性能,而非事务安全,MongoDB很适合业务系统中有大量“低价值”数据的场景,比如系统交易流水,系统日志。但是应当避免在高事务安全性的系统中使用MongoDB。
表结构不明确 在一些传统关系型数据库中,增加一个字段会锁住整个数据库/表,或者在执行一个重负载的请求时会明显造成其它请求的性能降级,当表数据量较大的时候甚至导致系统宕机。MongoDB作为文档类型数据库,对数据的格式规范就没有那么严格了增加字段或者减少字段不会对数据库和系统造成多大的影响。
持久化数据库 启动时,专门初始化一个线程不断循环每90 毫秒写入磁盘一次(所以敏感的比较重要的数据最好不要放MongoDB中)。
基于位置的数据查询 MongoDB支持二维空间索引,因此可以快速及精确的从指定位置获取数据。
文档模型和关系模型的区别
关系型数据库模型
id | name | sex | age | phone_id |
---|---|---|---|---|
1 | 张三 | 男 | 20 | 1 |
2 | 李四 | 男 | 21 | 2 |
id | user_id | phone | type |
---|---|---|---|
1 | 1 | 15100000001 | home |
2 | 1 | 15100000002 | company |
3 | 2 | 15100000003 | home |
4 | 2 | 15100000004 | company |
文档模型
[{
id : 1,
name : 张三,
sex : 男,
age : 20,
phones : [{
phone : 15100000001,
type : home
},{
phone : 15100000002
}]
},
{
id : 2,
name : 李四,
sex : 男,
age : 22,
phones : [{
phone : 15100000003,
type : home
},{
phone : 15100000004
}]
}]
关系型数据库结构 VS 非关系型数据库结构
MongoDB(非关系型) | RDBMS(关系型) |
---|---|
数据库(Database) | 数据库(Database) |
集合(Collection) | 表(Table) |
文档(Document) | 行(Row) |
列(Column) | 字段(field) |
索引(index) | 索引(index) |
文档模型的优点
读写效率高 由于文档模型把相关数据集中在一块,在普通机械盘上读数据的时候不用花太多时间去定位磁头,因此在IO性能上有先天独厚的优势;
可扩展能力强 关系型数据库很难做分布式的原因就是多节点海量数据关联有巨大的性能问题。如果不考虑关联,数据分区分库,水平扩展就比较简单;
动态模式 文档模型支持可变的数据模式,不要求每个文档都具有完全相同的结构。对很多异构数据场景支持非常好;
模型自然 文档模型最接近于我们熟悉的对象模型。从内存到存储,无需经过ORM的双向转换,性能上和理解上都很自然易懂。
MongoDB 文档模式设计的基本策略
1、先考虑内嵌, 直接按照你的对象模型来设计你的数据模型。如果你的对象模型数量不多,关系不是很复杂,那么直接一种对象对应一个集合就可以了。这点很重要
2、内嵌是文档模型的特色,可以充分利用MongoDB的富文档功能来享受我们刚才谈到的一些文档模型的性能和扩展性等特性。一般的一对一、一对多关系,比如说一个人多个地址多个电话等等都可以放在一个文档里用内嵌来完成。
3、但是有一些时候,使用引用则难以避免。比如说, 一个明星的博客可能有几十万或者几百万的回复,这个时候如果把评论放到一个数组里,可能会超出16M的限制。这个时候你可以考虑使用引用的方式,在主表里存储一个id值,指向另一个表中的 id 值。使用引用要注意的就是:从性能上讲,一般我们可能需要两次以上才能把需要的数据取回来。更加重要的是:需要把数据存放到两个集合里,但是目前为止MongoDB并不支持跨表的事务性,所以对于强事务的应用场景要谨慎使用。