为什么键名存储在MongodB中的文档中

时间:2012-07-11 09:40:59

标签: mongodb

我很好奇Kyle Banker的MongoDB In Action:

  

考虑所选键名的长度很重要,因为键名存储在文档中。这与RDBMS形成对比,其中列名始终与它们引用的行分开。因此,当使用BSON时,如果您可以使用dob代替date_of_birth作为键名,那么每个文档将节省10个字节。这可能听起来不是很多,但是一旦你有十亿个这样的文件,你只需使用一个较短的密钥名称就可以节省近10 GB的存储空间。这并不意味着你应该采取不合理的长度来确保小关键名称;要懂事。但是,如果您期望大量数据,节省关键名称将节省空间。

我对数据库服务器端未优化的原因感兴趣。集合中所有键名的内存中查找表是否会造成太大的性能损失而不值得节省空间?

3 个答案:

答案 0 :(得分:10)

您所指的通常称为“密钥压缩”*。有几个原因导致它没有实施:

  1. 如果您希望这样做,您现在可以非常轻松地在Application / ORM / ODM级别进行此操作。
  2. 在所有情况下,它不一定是性能**优势 - 认为具有许多关键名称的集合和/或在文档之间变化很大的键名。
  3. 在您拥有数百万份文档之前,它可能无法提供可衡量的性能**优势。
  4. 如果服务器执行此操作,则仍必须通过网络传输完整的密钥名称。
  5. 如果压缩的密钥名称是通过网络传输的,那么可读性确实会因使用javascript控制台而受损。
  6. 压缩整个JSON文档可能提供提供更好的性能优势。
  7. 与所有功能一样,有一个实施它的成本效益分析,并且(至少到目前为止)其他功能提供了更多的“降压”。

    对于未来的MongoDB版本,完全文档压缩是 [正在考虑] [1]。从3.0版开始提供(见下文)

    *键名称的内存中查找表基本上是LZW样式压缩的特例 - 这或多或少是大多数压缩算法所做的。

    **压缩提供了空间优势和性能优势。较小的文档意味着每个IO可以读取更多文档,这意味着在具有固定IO的系统中,每秒可以读取更多文档。

    更新

    MongoDB 3.0及更高版本现在具有WiredTiger存储引擎的完整文档压缩功能。

    有两种压缩算法:snappyzlib。目的是使snappy成为全方位性能的最佳选择,并使zlib成为最大存储容量的最佳选择。

    在我的个人(非科学,但与商业项目有关)实验中,快速压缩(我们没有评估zlib)提供了显着提高的存储密度,没有明显的净性能成本。事实上,在某些情况下表现稍好一些,大致与我先前的评论/预测一致。

答案 1 :(得分:3)

我认为将密钥名称与文档一起存储的原因之一是允许更容易扩展的schema-less数据库。每个文档都是自包含的,如果您将文档移动到另一个服务器(例如,通过复制或分片),您可以索引文档的内容,而无需引用单独的或集中的元数据,如映射密钥名称更紧凑的密钥ID。

由于MongoDB集合没有强制模式,因此对于同一集合中的每个文档,字段名称可能不同。在sharded环境中,对每个分片的插入是(有意)独立的,因此在文档级别,原始数据可能最终会有所不同,除非键映射能够按每个分片保持一致。

根据您的使用情况,密钥名称可能会或可能不会消耗相对于附带数据的大量空间。您始终可以通过将YourFriendlyKeyNames映射到更短的DB密钥等效项来解决应用程序/ ODM实现中的存储问题。

有一个开放的MongoDB Jira问题以及对have the server tokenize field names的一些进一步讨论,您可以投票选出以帮助确定在将来的版本中包含此功能的优先级。

MongoDB目前的设计目标包括动态模式,复制和运行模式的性能。高可用性,自动分片和就地更新......一个可能的权衡是一些额外的磁盘使用。

答案 2 :(得分:1)

必须在数据库中查找每个查询,这将是一个严重的惩罚 大多数驱动程序都允许您指定ElementName,以便域模型中的MyLongButReadablePropertyName在mongodb中变为mlbrpn

因此,当您在应用程序中进行查询时,它是转换查询的应用程序:

db.myCollection.find({"MyLongButReadablePropertyName" : "some value"})

db.myCollection.find({"mlbrpn" : "some value"})

高效的驱动程序,比如C#驱动程序缓存此映射,因此不需要为每个查询查找此内容。

回到你问题的标题:

  

为什么密钥名称存储在MongodDB文档中

这是搜索文件的唯一方法吗? 如果没有存储密钥名称,就没有可以搜索的密钥。

希望这有帮助