开始使用MongoDB之前应该知道的14件事(2)

在有查询优化器的数据库系统中,你编写的查询是说明你想要什么而不是如何获取它。这就像在餐馆中点餐;你通常只需要点菜,而不必对厨师发出详细的指令。

在MongoDB中,你是对厨师发指令。例如,你需要通过$match和$project确保管道中的数据尽早减少,排序只在数据减少时发生一次,查找按照你希望的顺序执行。查询优化器省去了不必要的工作,优化阶段顺序,选择连接类型,这会把你宠坏。MongoDB给了你更多的控制,但这种便利是有成本的。

Studio 3T这样的工具使构建准确的MongoDB聚合查询变得更容易。它的聚合编辑器特性使你可以一次对一个阶段应用管道操作符,你可以在每个阶段验证输入和输出,更便于调试。

使用快速写

永远不要把MongoDB设为低稳定性的高速写。看上去,“file-and-forget”模式使得写入速度变快了,因为命令在实际写入任何东西前就返回了。如果系统在数据写入磁盘之前崩溃了,就会丢失,存在出现不一致状态的风险。所幸,64位的MongoDB启用了“日志(Journaling)”。

MMAPv1和WiredTiger存储引擎都使用日志预防上述情况,不过,在日志关闭的情况下,WiredTiger也可以在还原过程中恢复到最后一致的。

日志可以确保数据库在恢复时处于一致状态,它会保存日志写入时的所有数据。日志写入的时间间隔可以使用运行时选项来配置。

为了确保写入,就要确保,而且提交间隔要和你能够承担的数据丢失相对应。

无索引排序

在搜索和聚合中,你经常希望排序数据。但愿那是在最后阶段完成的,在结果过滤之后,从而减少需要排序的数据量。即使在那个时候,你需要一个可以覆盖排序的索引。单键索引或混合索引都可以。

当没有合适的索引可用时,MongoDB就不得不在没有索引的情况下排序。对于排序操作中所有文档的总大小,,如果MongoDB达到了这个限值,它就会产生错误,或者有时候仅仅返回一个空的记录集

Lookup而没有索引支持

Lookup的功能和SQL联合查询类似。为了获得良好的性能,作为外键的键值上需要有索引。这并不明显,因为其使用并没有在explain()中报告。这些索引并不包含在explain()记录的索引里,那些索引是供管道操作符$match、$sort出现在管道开始时使用的。现在,。

不使用多条更新

db.collection.update()方法用于修改一个已存在文档的一部分或全部,或者是整个替换一个已存在的文档,这取决于你提供的。除非你设置multi参数,更新匹配查询条件的所有文档,否则它不会更新集合里的所有文档。这一点不是那么明显。

忘记哈希对象中键序的意义

在JSON中,一个对象包含一个无序集合,而该集合中有零个或多个名/值对,其中名是一个字符串,而值是一个字符串、数值、布尔值、空、对象或数组。

遗憾的是,BSON在做搜索时给顺序赋予了意义。在MongoDB中,嵌入对象中键的顺序很重要,也就是说,{ firstname: "Phil", surname: "factor" }和{ surname: "factor", firstname: "Phil" }就不匹配。这意味着,你必须保留文档中名/值对的顺序,如果你想确保可以找到它们的话。

混淆“null”和“undefined”

根据正式的JSON标准(ECMA-404第5节),“undefined”值在JSON中从来就是不合法的,虽然它事实上已经在JavaScript中使用。而且,它在BSON中是“deprecated”,会转换成$null,这并不是一个总令人满意的解决方案。。

使用$limit()而未用$sort()

通常,当你在MongoDB中开发时,仅仅查看查询或聚合返回的结果的样例会很有用。 $limit()就是为了满足这个要求,但是,它永远不应该出现在最终版本的代码中,除非你首先使用了$sort。这是因为,不这样的话,你就无法保证结果的顺序,你就无法可靠地“按页浏览”数据。为了确保可靠性,查询或聚合必须是“确定的”,就是说,它们每次执行都会给出相同的结果。包含$limit而不包含$sort的代码不是确定的,后续会导致难以跟踪的Bug。

小结

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/9b60cf3c6d6e7c1ac9422ad91db114da.html