MongoDB 索引大小是否取决于字段大小?
Does MongoDB index size depend on field size?
在MongoDb中有一个32位的int类型(4字节)和一个96位的ObjectId类型(12字节)。我注意到 32 位 int 字段上的索引比 ObjectId 字段上的索引大,而根据这个问题我期望相反:Are there any tools to estimate index size in MongoDB?
这是否特定于 ObjectId,这怎么可能?
这里有一些显示差异的统计数据,使用 MongoDB 3.2.9 和 mongodb-java-driver 3.2,默认配置(WiredTiger 引擎 + snappy 压缩级别)
"_id" 作为 ObjectId:
> db.objectId.stats()
{
"ns" : "test1.objectId",
"count" : 500000,
"size" : 20500000,
"avgObjSize" : 41,
"storageSize" : 6737920,
[...]
"nindexes" : 1,
"totalIndexSize" : 4300800,
"indexSizes" : {
"_id_" : 4300800
}
}
"_id" as int32(线性插入):
> db.int32linear.stats()
{
"ns" : "test1.int32linear",
"count" : 500000,
"size" : 16500000,
"avgObjSize" : 33,
"storageSize" : 5586944,
[...]
"nindexes" : 1,
"totalIndexSize" : 5255168,
"indexSizes" : {
"_id_" : 5255168
}
}
"_id" as 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();
}
}
我不确定但是:WildTiger 正在有效地压缩对象 ID 键。如果您查看它们是如何生成的,并且如果所有文档都以超快的速度(几秒钟内)插入,那么在一台机器上,对象 ID 将有一个很长的公共前缀。 WildTiger 的键前缀压缩会非常有效
那么为什么这不适用于递增整数?因为小端格式。
如果上述假设是正确的,在实际系统中,插入时间差距更大并且有许多服务器(分片),ObjectId 索引可能比 int 索引大一点——但仍然很漂亮大小合理。如果你想检查这个尝试关闭索引构建的压缩。
总的来说,我认为这是个好消息,因为问题不在于 int 索引很大,而是 ObjectId 索引是有效的——~10 bytes/entry 是合理的(尽管我可以想象做得更好) 假设除了每个文档的键之外还有一个记录 ID。
https://docs.mongodb.com/manual/reference/method/ObjectId/
p.s。我相信递增的 int 索引比随机的小一点,因为 mmap 对升序键进行了适度的优化。
在MongoDb中有一个32位的int类型(4字节)和一个96位的ObjectId类型(12字节)。我注意到 32 位 int 字段上的索引比 ObjectId 字段上的索引大,而根据这个问题我期望相反:Are there any tools to estimate index size in MongoDB?
这是否特定于 ObjectId,这怎么可能?
这里有一些显示差异的统计数据,使用 MongoDB 3.2.9 和 mongodb-java-driver 3.2,默认配置(WiredTiger 引擎 + snappy 压缩级别)
"_id" 作为 ObjectId:
> db.objectId.stats()
{
"ns" : "test1.objectId",
"count" : 500000,
"size" : 20500000,
"avgObjSize" : 41,
"storageSize" : 6737920,
[...]
"nindexes" : 1,
"totalIndexSize" : 4300800,
"indexSizes" : {
"_id_" : 4300800
}
}
"_id" as int32(线性插入):
> db.int32linear.stats()
{
"ns" : "test1.int32linear",
"count" : 500000,
"size" : 16500000,
"avgObjSize" : 33,
"storageSize" : 5586944,
[...]
"nindexes" : 1,
"totalIndexSize" : 5255168,
"indexSizes" : {
"_id_" : 5255168
}
}
"_id" as 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();
}
}
我不确定但是:WildTiger 正在有效地压缩对象 ID 键。如果您查看它们是如何生成的,并且如果所有文档都以超快的速度(几秒钟内)插入,那么在一台机器上,对象 ID 将有一个很长的公共前缀。 WildTiger 的键前缀压缩会非常有效
那么为什么这不适用于递增整数?因为小端格式。
如果上述假设是正确的,在实际系统中,插入时间差距更大并且有许多服务器(分片),ObjectId 索引可能比 int 索引大一点——但仍然很漂亮大小合理。如果你想检查这个尝试关闭索引构建的压缩。
总的来说,我认为这是个好消息,因为问题不在于 int 索引很大,而是 ObjectId 索引是有效的——~10 bytes/entry 是合理的(尽管我可以想象做得更好) 假设除了每个文档的键之外还有一个记录 ID。
https://docs.mongodb.com/manual/reference/method/ObjectId/
p.s。我相信递增的 int 索引比随机的小一点,因为 mmap 对升序键进行了适度的优化。