我想在开始使用MongoDB之前要了解的14件事

本文的翻译是在“非关系数据库”课程开始前夕进行的










强调:



  • 即使在MongoDB中它是可选的,设计架构也非常重要。
  • 同样,索引必须匹配您的架构和访问模式。
  • 避免使用大对象和大数组。
  • 注意MongoDB设置,尤其是在安全性和可靠性方面。
  • MongoDB没有查询优化器,因此在执行查询操作时必须小心。


我使用数据库已经很长时间了,但是直到最近才发现MongoDB。在开始使用之前,我需要了解一些信息。当一个人已经在某个领域有经验时,他们就对什么是数据库以及它们做什么有先入为主的想法。为了使其他人更容易理解,这里列出了一些常见错误。



创建未经身份验证的MongoDB服务器



不幸的是,默认情况下,MongoDB在安装时没有身份验证。在本地访问工作站是正常的。但是,由于MongoDB是喜欢使用大量内存的多用户系统,因此即使将其仅用于开发,最好将其放在具有尽可能多RAM的服务器上。通过默认端口在服务器上进行安装可能会出现问题,尤其是如果可以在请求中执行任何javascript代码的情况下(例如,$where作为注入的想法)。



有几种身份验证方法,但是最简单的方法是设置用户ID /密码。在考虑基于LDAP的奇妙身份验证时,请采用这个想法关于安全性,必须不断更新MongoDB,并且应始终检查日志以进行未经授权的访问。例如,我想选择其他端口作为默认端口。



记住将攻击面绑定到MongoDB



MongoDB安全检查表包含一些很好的技巧,可以降低网络入侵和数据泄漏的风险。很容易就忽略它,并说开发服务器不需要高度的安全性。但是,事情并不是那么简单,这适用于所有MongoDB服务器。特别是,除非有令人信服的理由来使用mapReducegroup$哪里,你应该在配置文件中写入禁止使用的任意JavaScript代码javascriptEnabled:false由于数据文件未在标准MongoDB中进行加密,因此请以具有完全文件访问权限专用用户运行MongoDB,该用户仅对其具有有限的访问权限,并且能够使用操作系统自己的文件访问控件。



电路设计错误



MongoDB不使用架构。但这并不意味着不需要该电路。如果您只想存储没有一致布局的文档,则保存起来既快捷又容易,但是要以后再检索它们就很难了值得一读



的经典文章“ MongoDB模式设计的6条经验法则”,而Studio 3T第三方工具中的“模式资源管理器”之类的功能值得定期进行模式验证。



不要忘记排序顺序



忘记排序顺序可能是任何其他错误配置中最令人沮丧和浪费的事情。 MongoBD默认使用二进制排序。但是它不太可能对任何人有用。区分大小写,对压力敏感的二元分类早在1980年代就被认为是古怪的时代错误,还有珠子,卡夫丹和卷曲的胡须。现在它们的使用是不可原谅的。在现实生活中,“摩托车”与“摩托车”相同。而“英国”和“英国”是一个地方。小写字母只是大写字母的等价字母。而且不要让我谈论变音排序。在MongoDB中创建数据库时使用不区分大小写的排序规则对应于系统用户的语言和文化这将大大简化您对字符串数据的搜索。



使用大型文档创建收藏



MongoDB很高兴在集合中托管最大16MB的大型文档,而GridFS专为大于16MB的大型文档而设计。但是,仅因为可以在其中放置大型文档,将它们放在此处并不是一个好主意。如果您将单个文档的大小保存为几千字节,将MongoDB像宽阔的SQL表中的行一样对待,则MongoDB的效果最佳。大型文档将成为性能问题的根源



创建具有大阵列的文档



文档可以包含数组。最好是数组中的元素数与四位数不相符。如果将元素频繁添加到数组,它将超出包含它的文档,并且需要移动它,这意味着索引也需要更新。当使用大型数组为文档重新索引时,索引通常会被覆盖,因为对于每个元素,都有一条记录存储其索引。当插入或删除文档时,也会发生重新索引。



MongoDB有一个所谓的“填充因子”,它为文档增长提供了空间,以最大程度地减少此问题。

您可能会认为无需索引数组就可以做到。不幸的是,由于缺少索引,您可能还有其他问题。由于从头到尾扫描文档,因此在数组末尾查找项目将花费更长的时间,并且与此类文档关联的大多数操作都将很



不要忘记聚合中各个阶段的顺序很重要



在查询优化器数据库系统中,您编写的查询是对要获取的内容的说明,而不是如何获取的说明。这种机制类似于在餐厅点菜:通常您只是点菜,而不向厨师给出详细说明。



在MongoDB中,您指导厨师。例如,您需要确保reduce使用$match尽早在管道中处理数据$project,并且排序仅在之后进行reduce,并且搜索必须按照所需的顺序进行。使用查询优化器可以消除不必要的工作,以最佳方式组织阶段并选择连接类型,这可能会损坏您。在MongoDB中,您以方便为代价拥有更多控制权。



像这样的工具Studio 3T将使在MongoDB中构建聚合查询变得容易聚合编辑器允许您一次仅一步一步地应用管道语句,并在每一步中验证输入和输出数据以简化调试。



使用快速录音



切勿设置高速但可靠性低的MongoDB写参数。这种“文件即忘记”模式似乎很快,因为该命令在写入之前返回。如果在将数据写入磁盘之前系统崩溃,它将丢失并且处于不一致状态。幸运的是,64位MongoDB已启用日志记录。



存储引擎MMAPv1和WiredTiger使用日志记录来防止这种情况,尽管如果禁用了日志记录,则WiredTiger可以恢复到最后匹配的检查点



日记可确保恢复后数据库处于一致状态,并保留所有数据直到被记录。输入频率是使用参数配置的commitIntervalMs



要确定记录,请确保在配置文件中启用了日志记录,并且记录(storage.journal.enabled)的频率适合您可以承受的丢失信息量。



无索引排序



搜索和汇总时,通常需要对数据进行排序。希望在过滤结果以减少要排序的数据量之后,在最后一个阶段中完成此操作。即使这样,您仍需要一个索引来排序您可以使用一个或多个索引。



如果没有合适的索引,MongoDB将没有它。排序操作中所有文档的总大小限制为32MB ,如果MongoDB达到此限制,它将抛出错误或返回空记录集



没有索引支持的搜索



搜索查询执行的功能类似于SQL中的JOIN操作。为了获得最佳性能,他们需要用作外键的键值的索引。这不是很明显,因为用法没有反映在中explain()此类索引是在中写入的索引的补充explain(),后者在管道的开头出现时由管道运算符$match依次使用$sort索引现在可以覆盖聚合管道的任何阶段



选择退出使用多次更新



该方法db.collection.update()用于更改现有文档的一部分或整个文档,直至完全替换为止,具体取决于您指定的参数update在您设置选项multi来更新所有符合查询条件的文档之前,它不会处理集合中的所有文档并不是很明显



不要忘记哈希表中键顺序的重要性



在JSON中,对象由零个或多个名称/值对的无序集合组成,其中名称是字符串,值是字符串,数字,布尔值,零,对象或数组。



不幸的是,BSON在搜索时非常重视顺序。在MongoDB中,内联对象中键的顺序很重要,即 { firstname: "Phil", surname: "factor" }是不一样的{ { surname: "factor", firstname: "Phil" }也就是说,如果要确保找到名称/值对,则必须保留其顺序。



不要混淆“ null”“ undefined”



根据官方JSON标准(ECMA-404,第5节),即使在JavaScript中使用了“ undefined”,该值从未在JSON中有效而且,对于BSON而言,它已被弃用并转换为,这并不总是一个好的解决方案。避免在MongoDB中使用“未定义”$null



$limit()使用$sort()



通常,当您在MongoDB中进行开发时,仅查看从查询或聚合返回的结果样本会很有帮助。这对于完成此任务很有用$limit(),但是除非已在代码的最终版本中使用它,否则它绝不应位于代码的最终版本中$sort该机制是必要的,因为否则您将无法保证结果的顺序,并且无法可靠地查看数据。在结果的顶部,您将获得不同的记录,具体取决于排序。为了可靠地工作,查询和聚合必须是确定性的,即每次执行时都产生相同的结果。$limit()存在但不存在的代码$sort将不能确定,并且可能随后导致难以跟踪的错误。



结论



对MongoDB感到沮丧的唯一方法是直接将其与其他类型的数据库(例如DBMS)进行比较,或者根据某些特定的期望来使用它。这就像将橙色与叉子进行比较。数据库系统有特定的目标。最好自己自己理解和欣赏这些差异。向MongoDB开发人员施加压力是可耻的,因为它迫使他们遵循DBMS路径。我想看到解决旧问题的新颖而令人兴奋的方法,例如确保数据完整性和构建可抵抗故障和恶意用户攻击的数据系统。



MongoDB 4.0的ACID事务性实现是一个很好的例子,说明了创新的重要性。现在,多文档和多语句事务是原子的。还可以调整获取锁和完成挂起的事务所需的时间,以及更改隔离级别。





阅读更多:






All Articles