Mongo 面试题
# Mongo 面试题
# MongoDB成为最好NoSQL数据库的原因是什么?
以下特点使得MongoDB成为最好的NoSQL数据库:
- 面向文件的
- 高性能
- 高可用性
- 易扩展性
- 丰富的查询语言
# MongoDB中的“Namespace”是什么?
MongoDB在集合中存储BSON(二进制交换和结构对象表示法)对象。集合名称和数据库名称的连接称为命名空间。
# MongoDB中的分片是什么?
跨多台机器存储数据记录的过程称为分片。它是一种MongoDB方法,以满足数据增长的需求。它是数据库或搜索引擎中的数据的水平分区。每个分区都称为切分或数据库切分。
# 在MongoDB中创建模式时,需要考虑哪些要点?
有几点需要考虑
- 根据用户需求设计模式
- 如果将对象组合在一起使用,则将它们组合到一个文档中。否则,将其分开
- 连接是在写的时候进行的,而不是在读取的时候进行的
- 对于大多数常见的用例,优化您的架构模式
- 在架构中进行复杂聚合
# 在MongoDB中创建集合和删除集合的语法是什么?
在MongoDB中创建集合的语法是db.createCollection(名称、选项)
在MongoDB中删除集合的语法是db.collection.drop()
# 解释分析器在MongoDB中的作用是什么?
MongoDB中包括了一个可以显示数据库中每个操作性能特点的数据库分析器。通过这个分析器你可以找到比预期慢的查询(或写操作);利用这一信息,比如,可以确定是否需要添加索引。
# 简要说明你能移动moveChunk目录下的旧文件吗?
是的,可以移动moveChunk目录中的旧文件,在正常的碎片操作期间,这些文件作为备份,一旦操作完成就可以删除。
# 为了进行安全备份,您可以使用MongoDB的哪些特性?
日志是MongoDB中可用于执行安全备份的功能。
# 说明Objecld由什么组成?
Objectld由
- 时间戳
- 客户机ID
- 客户端进程ID
- 3字节递增计数器
# 简要说明如何检查函数的源代码?
检查函数的源代码,不带任何括号,必须调用该函数。
# 什么是命令语法,告诉您是否在主服务器上?MongoDB允许多少个master?
命令语法Db.isMaster()将告诉您是否在主服务器上。MongoDB只允许一个主服务器,而couchDB允许多个主服务器。
# 解释一下MongoDB中的索引是什么?
索引是MongoDB中的特殊结构,它以易于遍历的形式存储一小部分数据集。索引按索引中指定的字段的值排序,存储特定字段或一组字段的值。
# 提到在MongoDB中使用索引的基本语法是什么?
MongoDB中使用的基本语法是>
db.COLLECTION_NAME.ensureIndex ({KEY:1})。
在这里,键是文档中出现的列(或KEY:VALUE对)的名称。
# 解释一下什么是MongoDB中的GridFS ?
为了存储和检索大文件,例如图像,视频文件和音频文件,使用GridFS。默认情况下,它使用两个文件fs.files和fs.chunks来存储文件的元数据和块。
# MongoDB有哪些替代方案?
Cassandra, CouchDB, Redis, Riak, Hbase都是不错的选择。
# 允许空值null吗?
对于对象成员而言,是的。然而用户不能够添加空值(null)到数据库丛集(collection)因为空值不是对象。然而用户能够添加空对象{}。
# 更新操作立刻fsync到磁盘?
不会,磁盘写操作默认是延迟执行的。写操作可能在两三秒(默认在60秒内)后到达磁盘。例如,如果一秒内数据库收到一千个对一个对象递增的操作,仅刷新磁盘一次。(注意,尽管fsync选项在命令行和经过getLastError_old是有效的)
# 如何执行事务/加锁?
MongoDB没有使用传统的锁或者复杂的带回滚的事务,因为它设计的宗旨是轻量,快速以及可预计的高性能。**可以把它类比成MySQL MylSAM的自动提交模式。**通过精简对事务的支持,性能得到了提升,特别是在一个可能会穿过多个服务器的系统里。
# 为什么我的数据文件如此庞大?
MongoDB会积极的预分配预留空间来防止文件系统碎片
# 什么是master或primary?
它是当前备份集群(replica set)中负责处理所有写入操作的主要节点/成员。在一个备份集群中,当失效备援(failover)事件发生时,一个另外的成员会变成primary。
# 什么是secondary或slave?
Seconday从当前的primary上复制相应的操作。它是通过跟踪复制oplog(local.oplog.rs)做到的。
# 我必须调用getLastError来确保写操作生效了么?
不用。不管你有没有调用getLastError(又叫"Safe Mode")服务器做的操作都一样。调用getLastError只是为了确认写操作成功提交了。当然,你经常想得到确认,但是写操作的安全性和是否生效不是由这个决定的。
# 数据在什么时候才会扩展到多个分片(shard)里?
MongoDB 分片是基于区域(range)的。所以一个集合(collection)中的所有的对象都被存放到一个块(chunk)中。只有当存在多于一个块的时候,才会有多个分片获取数据的选项。现在,每个默认块的大小是 64Mb,所以你需要至少 64 Mb 空间才可以实施一个迁移。
# 当我试图更新一个正在被迁移的块(chunk)上的文档时会发生什么?
更新操作会立即发生在旧的分片(shard)上,然后更改才会在所有权转移(ownership transfers)前复制到新的分片上。
# 如果块移动操作(moveChunk)失败了,我需要手动清除部分转移的文档吗?
不需要,移动操作是一致(consistent)并且是确定性的(deterministic);一次失败后,移动操作会不断重试;当完成后,数据只会出现在新的分片里(shard)。
# Mongo 为什么使用 B 树?
MongoDB 认为查询单个数据记录远比遍历数据更加常见,由于 B 树的非叶结点也可以存储数据,所以查询一条数据所需要的平均随机 IO 次数会比 B+ 树少。
# MySQL 与 Mongo 的使用场景的区分?
Mongo 适合归并数据的场景,比如用户标签场景,获取一个用户在所有场景中的标签是常态需求。
MySQL适合列表;Mongo 适合详情。
# Mongo 为什么不使用 Hash 作为数据结构?
如果我们使用哈希,那么对于所有单条记录查询的复杂度都会是 O(1)
,但是遍历数据的复杂度就是 O(n)
;如果使用 B+ 树,那么单条记录查询的复杂度是 O(log n)
,遍历数据的复杂度就是 O(log n) + X
,这两种不同的数据结构一种提供了最好的单记录查询性能,一种提供了最好的遍历数据的性能,但是这都不能满足 MongoDB 面对的场景 —— 单记录查询非常常见,**但是对于遍历数据也需要有相对较好的性能支持,**哈希这种性能表现较为极端的数据结构往往只能在简单、极端的场景下使用。
# Mongo 支持哪些数据结构?
LSM 和 B 树。
LSM 会比 B 树在写性能方面会更好。
无论是 B 树还是 B+ 树,向这些数据结构组成的索引文件中写入记录都需要执行的磁盘随机写,LSM 树的优化逻辑就是牺牲部分的读性能,将随机写转换成顺序写以优化数据的写入。
之所以选B树作为默认数据结构,是因为 B 树在查询方面性能比 LSM 优秀,LSM 更适合在写性能有极端要求的场景中。
# Mongo 事务?
用户的每个请求可以指定额外的扩展字段,主要包括:
- lsid: 请求所在 Session 的 ID, 也称 logic session id
- txnNmuber: 请求对应的事务号,事务号在一个 Session 内必须单调递增
- stmtIds: 对应请求里每个操作(以insert为例,一个insert命令可以插入多个文档)操作ID
实际上,用户在使用事务时,是不需要理解这些细节,MongoDB Driver 会自动处理,Driver 在创建 Session
时分配 lsid,接下来这个 Session
里的所以操作,Driver 会自动为这些操作加上 lsid,如果是事务操作,会自动带上 txnNumber。
值得一提的是,Session
lsid 可以通过调用 startSession
命令让 server 端分配,也可以客户端自己分配,这样可以节省一次网络开销;而事务的标识,MongoDB 并没有提供一个单独的 startTransaction
的命令,txnNumber 都是直接由 Driver 来分配的,Driver 只需保证一个 Session 内,txnNumber 是递增的,server 端收到新的事务请求时,会主动的开始一个新事务。
# 事务中的复制?
复制集配置下,MongoDB 整个事务在提交时,会记录一条 oplog(oplog 是一个普通的文档,所以目前版本里事务的修改加起来不能超过文档大小 16MB的限制),包含事务里所有的操作,备节点拉取oplog,并在本地重放事务操作。
# 如何保证事务时序统一?
MongoDB 通过 oplog 时间戳来标识全局顺序,而 WiredTiger 通过内部的事务ID来标识全局顺序,在实现上,2者没有任何关联。这就导致在并发情况下, MongoDB 看到的事务提交顺序与 WiredTiger 看到的事务提交顺序不一致。
通过事务时间戳(transaction timestamp)机制解决这个问题。
# 事务回滚策略?
当复制集节点需要回滚时,直接调用 WiredTiger 接口,将数据回滚到某个稳定版本(实际上就是一个 Checkpoint),这个稳定版本则依赖于 stable timestamp
。WiredTiger 会确保 stable timestamp
之后的数据不会写到 Checkpoint里,MongoDB 根据复制集的同步状态,当数据已经同步到大多数节点时(Majority commited),会更新 stable timestamp
,因为这些数据已经提交到大多数节点了,一定不会发生 ROLLBACK,这个时间戳之前的数据就都可以写到 Checkpoint 里了。
MongoDB 需要确保频繁(及时)的更新 stable timestamp
,否则影响 WT Checkpoint 行为,导致很多内存无法释放。例如主备延时很大,导致数据一直没有被同步到大多数节点,这时主上 stable timestamp
就无法更新,内存不断积累就可能把 cache 撑满。