2016-09-21 107 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