2016-09-21 121 views
0

在MongoDb中,有32位int類型(4字節)和96位ObjectId類型(12字節)。我注意到在32位int域上的索引大於ObjectId域,而根據這個問題,我期待着相反的結果:Are there any tools to estimate index size in MongoDB?MongoDB索引大小是否取決於字段大小?

這是特定於ObjectId的,它怎麼可能?

以下是示出差異,使用MongoDB的3.2.9和MongoDB-java的驅動器3.2的默認配置(WiredTiger發動機+活潑的壓縮水平)

「_id」 爲的ObjectId一些統計:

> db.objectId.stats() 
{ 
    "ns" : "test1.objectId", 
    "count" : 500000, 
    "size" : 20500000, 
    "avgObjSize" : 41, 
    "storageSize" : 6737920, 
    [...] 
    "nindexes" : 1, 
    "totalIndexSize" : 4300800, 
    "indexSizes" : { 
     "_id_" : 4300800 
    } 
} 

「_id」 作爲INT32(線性插入):

 > db.int32linear.stats() 
{ 
    "ns" : "test1.int32linear", 
    "count" : 500000, 
    "size" : 16500000, 
    "avgObjSize" : 33, 
    "storageSize" : 5586944, 
    [...] 
    "nindexes" : 1, 
    "totalIndexSize" : 5255168, 
    "indexSizes" : { 
     "_id_" : 5255168 
    } 
} 

「_id」 作爲INT32(隨機插入):

> db.int32random.stats() 
{ 
    "ns" : "test1.int32random", 
    "count" : 500000, 
    "size" : 16500000, 
    "avgObjSize" : 33, 
    "storageSize" : 5595136, 
    [...] 
    "nindexes" : 1, 
    "totalIndexSize" : 5378048, 
    "indexSizes" : { 
     "_id_" : 5378048 
    } 
} 

這裏是重現該測試的代碼:

import com.mongodb.MongoClient; 
import com.mongodb.client.MongoCollection; 
import com.mongodb.client.MongoDatabase; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
import org.bson.Document; 

public class Main { 

    public static void main(String[] args) { 

     List<Document> listDoc = new ArrayList<>(); 

     MongoClient mongoClient = new MongoClient(); 
     MongoDatabase db = mongoClient.getDatabase("test1"); 

     MongoCollection<Document> objectId = db.getCollection("objectId"); 
     MongoCollection<Document> int32linear = db.getCollection("int32linear"); 
     MongoCollection<Document> int32random = db.getCollection("int32random"); 

     for(int i = 0; i<500000; i++){ 
      listDoc.add(new Document("field", "content")); 
     } 
     objectId.insertMany(listDoc); 
     listDoc.clear(); 

     for (int i = 0; i<500000; i++){ 
      listDoc.add(new Document("_id", i).append("field", "content")); 
     } 
     int32linear.insertMany(listDoc); 
     // unsort the array 
     Collections.shuffle(listDoc); 

     int32random.insertMany(listDoc); 

     mongoClient.close(); 

    } 
} 
+0

哪個存儲引擎,WildTiger或mmap?不是一個答案,而是一些要嘗試的事情:隨機化而不是有序的int值,並且在測試之前刪除集合而不是刪除文檔以獲得乾淨的起點,因爲如果您只刪除了所有的刪除分配區域記錄。 – user3973

+0

這是與有線Tiger發動機。我根據你的評論更新了測試,但仍然得到相同的結果(請參閱我的編輯) – felix

回答

1

我不能肯定,但:WildTiger被有效地壓縮該對象ID密鑰。如果你看看它們是如何生成的,並且如果所有文檔都是在一臺機器上快速(幾秒鐘)超級插入的,那麼對象ID將會有一個非常長的公共前綴。 WildTiger的關鍵前綴壓縮將非常有效。

那麼爲什麼這不適用於遞增整數?由於小端格式。

如果上述假設是正確的,那麼在實際系統中,插入時間間隔更多並且存在很多服務器(分片)時,ObjectId索引可能會比int索引大一點 - 但仍然非常合理在尺寸方面。如果你想檢查這個嘗試關閉索引構建壓縮。

總的來說,我認爲這是個好消息,因爲問題不在於int索引很大,而在於ObjectId索引是有效的 - 在給定的情況下,〜10字節/條目是合理的(儘管我可以想象做得更好)是除了每個文檔的關鍵字之外的記錄標識。

https://docs.mongodb.com/manual/reference/method/ObjectId/

p.s.我相信遞增的int索引比隨機的索引略小,因爲在mmap中對遞增鍵進行了適度的優化。

+0

你是對的,如果我在插入數據前禁用prefixCompression,int32linear上的索引大小不會改變,但索引大小爲objectId double(「 indexSizes「:{」_id_「:9818112})!感謝您的照顧 – felix