长字符串字段名称如何影响 MongoDB 数据库大小?

Ior*_*nis 7 mongodb python

我正在使用 MongoDB,我的字段名称是 10-20 个字符的字符串。一个典型的文档由 30.000 列组成,其中大部分是浮点数,如 1.2、10.5、2.55。它的大小是 1MB。

长字符串字段名称会影响 MongoDB 数据库的大小吗?

Ada*_*m C 7

这在开发人员常见问题解答中包含,一些相关摘录:

MongoDB 将所有字段名称存储在每个文档中。对于大多数文档,这代表了文档所用空间的一小部分;但是,对于小文档,字段名称可能会按比例表示大量的空间

而且,只是关于索引的一个说明:

较短的字段名称不会减少索引的大小,因为索引具有预定义的结构

因此,是的,减少字段名称大小将使存储更高效,尽管它不会对索引大小产生影响。您所做的节省是否值得(相对于描述性的丧失)将取决于您。作为近似值,如果您将字段名称从 20(例如)减少到 2 个字符,则每个字段可能会节省大约 16 个字节,这意味着文档大小将减少 40% 以上(~400k)。

这是使用 MongoDB shell 进行估算的一种简单方法:

$ ./mongo --nodb
MongoDB shell version: 3.0.2
> testObject = {"12345678901234567890" : 1.23324}
{ "12345678901234567890" : 1.23324 }
> Object.bsonsize(testObject)
35
> testObject = {"1" : 1.23324}
{ "1" : 1.23324 }
> Object.bsonsize(testObject)
16
> testObject = {"12" : 1.23324}
{ "12" : 1.23324 }
> Object.bsonsize(testObject)
17
Run Code Online (Sandbox Code Playgroud)

Object.bsonsize方法将以字节为单位为您提供任何文档的近似大小,但不包括在数据库中存储文档时实际使用的填充、索引等。因此,这些都是非常近似的数字 - 我建议使用实际数据进行测试以获得更明确的示例。


Nea*_*ers 6

我执行了一些基准测试,将 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)