基础
mongodb是什么?
一个基于分布式文件存储的开源NoSQL数据库系统。
MongoDB的存储引擎
与mysql一样,mongo也是采用的插件式的存储引擎架构,支持不同类型的存储引擎。不同的存储引擎解决不同场景的问题。在创建数据库或集合时,可以指定存储引擎。
主要是有两种存储引擎:
- WiredTiger 存储引擎:自mongo3.2版本以后,默认的就是WiredTiger存储引擎。
- In-Memory 存储引擎:在mongodb Enterprise中可用。它不是将文档存储在磁盘上,而是将他们保留在内存中以获得更可预测的数据延迟。
WiredTiger是基于LSM Tree 还是 B+Tree?
参考资料:WiredTiger存储引擎之一:基础数据结构分析
WiredTiger默认配置的是B-Tree结构。
在B-Tree中,从上往下依次为Root节点、内部节点和叶子节点,每个节点就是一个Page,数据以Page为单位在内存和磁盘间进行调度,每个Page的大小决定了相应节点的分支数量,每条索引记录会包含一个数据指针,指向一条数据记录所在文件的偏移量。
磁盘上的基础数据结构:
对于WiredTiger存储引擎来说,集合所在的数据文件和相应的索引文件都是按B-Tree结构来组织的,不同之处在于数据文件对应的B-Tree叶子结点上除了存储键名外(keys),还会存储真正的几何数据(values),所以数据文件的存储结构也可以说是一种B+Tree,如下图:
从图中可以看到,B+Tree中的leaf page包含一个页头(page header)、块头(block header)和真正的数据(key/value),其中页头定义了页的类型、叶总实际荷载数据的大小、页中记录的条数等信息;块头定义了此页的checksum、块在磁盘上的寻址位置等信息。
WiredTiger有一个块设备管理的模块,用来为page分配block。如果要定位某一行数据(key/value)的位置,可以先通过block的位置找到此page(相对于文件起始位置的偏移量),再通过page找到行数据的相对位置,最后可以得到行数据相对于文件起始位置的偏移量offsets。由于offsets是一个8字节大小的变量,所以WiredTiger磁盘文件的大小,其最大值可以非常大(2^64 bit)。
内存上的基础数据结构
WiredTiger会按需将磁盘的数据以page为单位加载到内存,同时在内存会构造相应的B Tree来存储这些数据。为了高效的支撑CRUD等操作以及将内存里面发生变化的数据持久化到磁盘上,WiredTiger也会在内存里面维护其他几种数据结构,如图:
- 内存中B-Tree包含三种类型的page,即rootpage、internal page和 leaf page,前两者包含指向其子叶的page index指针,不包含集合中的真正数据,leaf page包含集合中的真正数据即keys/value和指向父页的home指针。
MongoDB的存储结构是什么?
由三个单元组成:
- 文档(Document):MongoDB中最基本的单元,由BSON键值对(key-value)组成,类似于关系型数据库中的行(row)。
- 集合(Collection):一个集合可以包含多个文档,类似于关系型数据库中的表(table)。
- 数据库(Database):一个数据库中可以包含多个集合,可以在MongoDB中创建多个数据库,类似于关系型数据库中的数据库(Batabase)。
也就是说,MongoDB将数据记录存储为文档(更具体来说是BSON文档),这些文档在集合中聚集在一起,数据库中存储一个或者多个文档集合。
MongoDB的优势有哪些?
- 面向集合和文档的存储,以json格式的文档保存数据。
- 高性能,支持document中嵌入document减少了数据库系统上的I/O操作以及具有完整的索引支持,支持快速查询。
- 高效的传统存储方式:支持二进制数据及大型对象。
- 高可用性,数据复制集,MongoDB数据库支持服务器之间的数据复制来提供自动故障转移。
- 高可扩展性,分片将数据分布在多个数据中心,MongoDB支持基于分片创建数据区域。
- 丰富的查询功能,聚合管道、全文搜索以及地理空间查询。
- 支持多个存储引擎。WiredTiger存储引擎、In-Memory存储引擎。
索引类型有哪些?
- 单字段索引(Single Field Indexes)
- 复合索引(Compound Indexes)
- 多键索引(Multikey Indexes)
- 全文索引(text Indexes)
- Hash索引(Hash Indexes)
- 通配符索引(Wildcard Indexes)
- 2dsphere索引(2dsphere Indexes)
如何优化MongoDB查询性能?
为查询字段创建索引:在查询频繁的字段上创建索引,能够提高查询速度。
限制查询结果的数量:可以使用skip()和limit()方法分页,减少查询结果的大小。
只查询需要的字段:使用projection或者特定字段查询的方式,避免查询所有字段,减少网络传输带宽。
使用聚合查询:使用聚合查询代替多个单独的查询语句,可以提高性能。
为数据结构优化设计:为了优化结构设计,尽可能减少重复的数据。
MongoDB的复制如何工作?
复制工作是基于主从复制实现的。其中一个节点被定义为主节点,使用replica set的方式,其他的节点被定义为备份节点,数据会进行实时同步。在某些情况下,主节点可能会失效或消失。这时候从节点将被提升为主节点继续工作。
MongoDB的副本集是什么?
副本集是一组备份节点,用于实现高度的可用性。副本集维护多个数据节点,其中的 一个被定义为主节点,其他的节点都被定义为备份节点。如果主节点在崩溃,选择另外一个节点作为主节点。
在哪些场景使用MongoDB?
- 大数据
- 内容管理系统
- 移动端Apps
- 数据管理
如何理解MongoDB中的GridFS机制,MongoDB为何使用GridFS来存储文件?
GridFS是一种将大型文件存储在MongoDB中的文件规范。
使用GridFS可以将大问价分割成多个小文档存放,这样我们能够有效的保存大文档,而且解决了BSON对象有限制的问题。
复制集节点类型有哪些?
- 优先级0型(Priority 0)节点
- 隐藏型(Hidden)节点
- 延迟型(Delayed)节点
- 投票型(Vote)节点以及不可投票节点
更新操作会立刻fsync到磁盘?
不会。
磁盘写操作默认是延迟执行的。写操作可能在两三秒(默认在60s内)后到达磁盘。例如,如果1秒内数据库收到一千个对一个对象递增的操作,仅刷新磁盘一次。
MongoDB支持存储过程吗?如果支持的话,怎么用?
MongoDB支持存储过程,它是javascript写的,保存在db.system.js表中。
如果一个分片(shard)停止或者很慢的时候,发起一个查询会怎样?
如果一个分片停止了,除非查询设置了partial选项,否则查询会返回一个错误。
如果一个分片响应很慢,MongoDB会等待它的响应。