缩短MongoDB属性名称是否值得?

raa*_*m86 15 mongodb database-schema

使用mongoDB,express和Node.js博客中,作者提到缩短属性名称是个好主意:

....经常报告mongoDB的问题是磁盘上数据的大小...每个记录都存储了所有的字段名称....这意味着拥有属性通常可以更节省空间例如't',或'b'而不是'title'或'body',但是为了避免混淆,除非真正需要,否则我会避免这种情况!

我知道如何做到的解决方案.我更感兴趣的是什么时候才真正需要?

Rob*_*obG 22

引用Donald Knuth的话:

过早优化是编程中所有邪恶(或至少大部分)的根源.

然而,构建您的应用程序似乎最合理,可维护和合乎逻辑.然后,如果您遇到性能或存储问题,请处理那些影响最大的问题,直到表现令人满意或者收益递减规则意味着进一步优化没有意义.

如果您不确定特定设计决策的影响(如长属性名称),请创建一个原型来测试各种假设(例如"将更短的属性名称节省更多空间").不要指望测试的结果是决定性的,但是它可能会教你不想要学习的东西.

  • 真*但*有时您可以预见到问题.如果您知道a)您的数据库将看到重负载,b)集合将增长到包含大量记录和c)字段名称的大小相对于集合中的数据大小然后您可以合理地预测问题.考虑一下,如果你发现在创建大量记录之后只有*存在这个问题,MongoDB会让纠正变得痛苦,甚至可能需要使用db的任何应用程序的停机时间. (17认同)
  • 当然,设计过程必须考虑非功能性要求,例如主机环境,可用空间,性能等.应该检查设计以确保它可能满足这些要求,测试将指示应用程序是否成功以及是否(以及什么)重新灭生动作可能需要很长时间才能投入生产.这不是过早优化,而是针对需求进行测试. (2认同)
  • 我只是认为这不是一个好的答案。小优化与大回报之间的平衡总是会获胜。我现在感觉到了,因为我有很大的键,数据库中就有大量数据,而且现在优化的成本是巨大的。 (2认同)

Joh*_*yHK 12

除非您自己的情况和测试提供了改变这些优先级的具体原因,否则将有意义的名称的优先级保持在短名称的优先级之上.

正如提到的评论SERVER-863,如果你使用的MongoDB 3.0+启用与活泼的压缩WiredTiger存储选项,长字段名变得的压缩有效地照顾缩短为你的问题.


phi*_*ate 6

最重要的是:所以保持紧凑,因为它仍然有意义.

我不认为这是真正需要缩短为一个字母的名字.无论如何,你应该尽可能地缩短它们,并且你觉得它很舒服.假设你有一个用户名:{FirstName,MiddleName,LastName}你甚至可以选择名字:{first,middle,last}.如果你觉得舒服,你的姓名可能会很好:{f,m,l}.
您应该使用短名称:因为它会消耗磁盘空间,内存,因此可能会使您的应用程序变慢(内存中保留的对象越少,查找时间越慢,因为更大的查询时间和更长的查询时间,因为搜索数据需要更长的时间).
一个好的模式文档可能会告诉开发人员t代表城镇而不是标题.根据您的堆栈,您甚至可以隐藏开发人员通过一些帮助工具来处理这些快捷方式来映射它.

最后我要说的是,你没有时间和方式来缩短你的模式名称.它在很大程度上取决于您的环境和要求.但是如果你能提供一个很好的文档来解释所有内容和/或提供工具来简化开发人员和管理员的生活,那么你就可以保持紧凑.无论如何管理员可能会直接与mongodb交互,所以我想不应该错过一个好的文档.


Nea*_*ers 5

我执行了一些基准测试,将 Excel 中的 252 行数据上传到两个集合 testShortNames 和 testLongNames 中,如下所示:

长名称:

{
    "_id": ObjectId("6007a81ea42c4818e5408e9c"),
    "countryNameMaster": "Andorra",
    "countryCapitalNameMaster": "Andorra la Vella",
    "areaInSquareKilometers": 468,
    "countryPopulationNumber": NumberInt("77006"),
    "continentAbbreviationCode": "EU",
    "currencyNameMaster": "Euro"
}
Run Code Online (Sandbox Code Playgroud)

简称:

{
    "_id": ObjectId("6007a81fa42c4818e5408e9d"),
    "name": "Andorra",
    "capital": "Andorra la Vella",
    "area": 468,
    "pop": NumberInt("77006"),
    "continent": "EU",
    "currency": "Euro"
}
Run Code Online (Sandbox Code Playgroud)

然后,我获取了每个文件的统计信息,保存在磁盘文件中,然后对两个文件进行“比较”:

pprint.pprint(db.command("collstats", dbCollectionNameLongNames))
Run Code Online (Sandbox Code Playgroud)

下图显示了两个感兴趣的变量:大小和存储大小。我的阅读表明 storageSize 是压缩后使用的磁盘空间量,基本上 size 是未压缩的大小。所以我们看到 storageSize 是相同的。显然,Wired Tiger 引擎压缩字段名的效果相当好。 在此输入图像描述

然后,我运行一个程序来检索每个集合中的所有数据,并检查响应时间。

尽管这是一个亚秒级的查询,但长名称始终花费大约 7 倍的时间。当然,将较长的名称从数据库服务器发送到客户端程序会花费更长的时间。

-------LongNames-------
Server Start DateTime=2021-01-20 08:44:38
Server End   DateTime=2021-01-20 08:44:39
StartTimeMs= 606964546  EndTimeM= 606965328
ElapsedTime MilliSeconds= 782
-------ShortNames-------
Server Start DateTime=2021-01-20 08:44:39
Server End   DateTime=2021-01-20 08:44:39
StartTimeMs= 606965328  EndTimeM= 606965421
ElapsedTime MilliSeconds= 93
Run Code Online (Sandbox Code Playgroud)

在 Python 中,我只是执行了以下操作(我必须实际循环遍历项目以强制读取,否则查询仅返回游标):

results = dbCollectionLongNames.find(query)
for result in results:
    pass
Run Code Online (Sandbox Code Playgroud)