22

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

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

我知道如何做到这一点的解决方案。我更感兴趣的是什么时候真正需要这样做?

4

6 回答 6

22

引用Donald Knuth 的话:

过早的优化是编程中万恶(或至少是大部分)的根源。

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

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

于 2012-10-08T23:45:55.780 回答
15

保持有意义名称的优先级高于短名称的优先级,除非您自己的情况和测试提供了更改这些优先级的特定理由。

正如SERVER-863的评论中所提到的,如果您使用MongoDB 3.0+和 WiredTiger 存储选项并启用了快速压缩,那么长字段名称就不再是一个问题,因为压缩有效地为您处理了缩短问题。

于 2015-07-30T03:13:44.923 回答
8

底线:所以保持紧凑,因为它仍然有意义。

我认为这并不是真正需要缩短为一个字母的名称。无论如何,您应该尽可能缩短它们,并且您对此感到满意。假设您有一个用户名:{FirstName, MiddleName, LastName},您可能最好使用偶数名称:{first, middle, last}。如果你觉得舒服,你可能会觉得name:{f, m,l} 没问题。
您应该使用短名称:因为它会消耗磁盘空间、内存,因此可能会在某种程度上减慢您的应用程序(内存中保存的对象更少,由于更大的大小和更长的查询时间导致查找时间更慢,因为查找数据需要更长的时间)。
一个好的模式文档可能会告诉开发人员 t 代表城镇而不是标题。根据您的堆栈,您甚至可以通过一些辅助工具来隐藏开发人员使用这些快捷方式来映射它。

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

于 2012-10-09T09:36:20.230 回答
3

加上我的 2 美分。

在设计数据模型时,可以避免使用长命名属性(或“AbnormallyLongNameAttributes”)。在我之前的组织中,我们测试了保留短命名属性策略,例如,组织定义了 4-5 个字母编码的字符串,例如:

  1. 名字 = FSTNM,
  2. 姓氏 = LSTNM,
  3. 月盈亏百分比 = MTPCT,
  4. 同比销售预测 = YOYSP,依此类推..)

虽然我们观察到查询性能的改进,主要是由于通过网络传输的数据大小减少,或者(因为我们将 JAVA 与 MongoDB 一起使用)减少了 MongoDB 文档/Java Map 堆空间中“键”的长度,性能的整体提升不到 15%。

在我个人看来,这是一个微优化,需要额外的成本(和一个巨大的头痛)来维护/设计一个额外的系统来管理每个数据模型的数据属性字典。该系统在调试应用程序/回答客户查询时需要具有组织范围的透明度。

如果您发现自己处于使用此策略将性能提高 20% 对您有利可图的位置,可能是时候扩展您的 MongoDB 服务器/选择其他一些数据建模/查询策略,或者选择不同的完全数据库。

于 2018-01-09T06:40:52.057 回答
2

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

长名称:

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

简称:

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

然后我得到了每个的统计数据,保存在磁盘文件中,然后对这两个文件做了一个“差异”:

pprint.pprint(db.command("collstats", dbCollectionNameLongNames))

下图显示了两个感兴趣的变量:size 和 storageSize。我的阅读表明 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

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

results = dbCollectionLongNames.find(query)
for result in results:
    pass
于 2021-01-20T15:01:54.103 回答
1

如果使用详细的 xml,尝试使用自定义名称来改善它可能非常重要。SERVER-863 票证中的用户评论在他的案例中说;我正在存储外部定义的 XML 对象,并带有详细的命名:字段名可能是总记录大小的 70%。因此,就 I/O 和内存效率而言,字段名称标记化可能是一个巨大的胜利。

于 2014-05-20T20:30:28.767 回答