長字元串欄位名稱如何影響 MongoDB 數據庫大小?
我正在使用 MongoDB,我的欄位名稱是 10-20 個字元的字元串。一個典型的文件由 30.000 列組成,其中大部分都填充了浮點數,例如 1.2、10.5、2.55。它的大小是 1MB。
長字元串欄位名稱會影響 MongoDB 數據庫的大小嗎?
這在開發人員常見問題解答中有所介紹,一些相關摘錄:
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
該
Object.bsonsize
方法將為您提供任何文件的近似大小(以字節為單位),但不包括在數據庫中儲存文件時實際使用的填充、索引等。因此,這些都是非常近似的數字——我建議使用實際數據進行測試以獲得更明確的範例。
我執行了一個小基準測試,我將 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