MongoDB是否产生了超过100%的存储开销?i、 例如,我插入22GB的数据,它在磁盘上占用50GB的空间

MongoDB是否产生了超过100%的存储开销?i、 例如,我插入22GB的数据,它在磁盘上占用50GB的空间,mongodb,mongodb-.net-driver,nosql,Mongodb,Mongodb .net Driver,Nosql,我做了一个简单的实验来测试MongoDB的性能和磁盘使用率我插入了22GB的数据,但它在磁盘上占用了50GB。我将在下面详细描述这个实验 设置: 版本-MongoDB 2.0.2 环境:1)没有任何复制或分片的单个节点。2) 虚拟机通过VirtualBox。3) Linux Ubuntu 64位。4) 100GB固定虚拟磁盘和1GB内存 语言:C#&MongoDB C#驱动程序 目标和程序:非常简单。我只是不断地创建一个新的{KEY,VALUE}对并将其插入MongoDB *插入次数=1024

我做了一个简单的实验来测试MongoDB的性能和磁盘使用率我插入了22GB的数据,但它在磁盘上占用了50GB。我将在下面详细描述这个实验

设置:
  • 版本-MongoDB 2.0.2
  • 环境:1)没有任何复制或分片的单个节点。2) 虚拟机通过VirtualBox。3) Linux Ubuntu 64位。4) 100GB固定虚拟磁盘和1GB内存
  • 语言:C#&MongoDB C#驱动程序
  • 目标和程序:非常简单。我只是不断地创建一个新的{KEY,VALUE}对并将其插入MongoDB
  • *插入次数=1024*1024*1024/3
  • 键的大小=20字节(字节数组),每次插入递增1的计数器,即键={1,2,3,…,1024*1024*1024}
  • 值的大小=100字节(字节数组),通过随机类随机生成
结果: 所以这个实验意味着我希望在MongoDB中插入大约40GB的数据(每次插入120字节的数据),我相信这足够简单。但是,当实际插入的数据达到22GB时,我停止了,因为我发现了存储开销问题我插入的实际数据约为22GB,但所有indexdb.*文件的大小都为50GB。因此,存储开销超过100%。

我自己的想法: 我读过很多MongoDB的文档。根据我所读到的,存储可能有两种开销

  • oplog。但这意味着要限制大约5%的磁盘空间。在我的例子中,它的上限约为5GB
  • 预分配的数据文件。我没有更改mongod的任何设置,所以我认为它是2GB的。让我假设使用中的最新2GB文件几乎是空的,因此总的开销最多为4GB
  • 因此,根据我的计算,无论我插入的数据大小如何,都应该最多有9GB的开销。但是现在的开销是50GB-22GB=28GB。我一点也不知道28GB的内存是什么。如果这个开销总是超过100%,那就相当大了

    谁能给我解释一下吗


    以下是我从Mongoshell获得的一些mongodb统计数据

    db.serverStatus() {
    "host" : "mongodb-VirtualBox",
    "version" : "2.0.2",
    "process" : "mongod",
    "uptime" : 531693,
    "uptimeEstimate" : 460787,
    "localTime" : ISODate("2012-01-26T16:32:12.888Z"),
    "globalLock" : {
         "totalTime" : 531692893756,
         "lockTime" : 454374529354,
         "ratio" : 0.8545807827977436,
         "currentQueue" : {
              "total" : 0,
              "readers" : 0,
              "writers" : 0
         },
         "activeClients" : {
              "total" : 0,
              "readers" : 0,
              "writers" : 0
         }
    },
    "mem" : {
         "bits" : 64,
         "resident" : 292,
         "virtual" : 98427,
         "supported" : true,
         "mapped" : 49081,
         "mappedWithJournal" : 98162
    },
    "connections" : {
         "current" : 3,
         "available" : 816
    },
    "extra_info" : {
         "note" : "fields vary by platform",
         "heap_usage_bytes" : 545216,
         "page_faults" : 14477174
    },
    "indexCounters" : {
         "btree" : {
              "accesses" : 3808733,
              "hits" : 3808733,
              "misses" : 0,
              "resets" : 0,
              "missRatio" : 0
         }
    },
    "backgroundFlushing" : {
         "flushes" : 8861,
         "total_ms" : 26121675,
         "average_ms" : 2947.93759169394,
         "last_ms" : 119,
         "last_finished" : ISODate("2012-01-26T16:32:03.825Z")
    },
    "cursors" : {
         "totalOpen" : 0,
         "clientCursors_size" : 0,
         "timedOut" : 0
    },
    "network" : {
         "bytesIn" : 44318669115,
         "bytesOut" : 50995599,
         "numRequests" : 201846471
    },
    "opcounters" : {
         "insert" : 0,
         "query" : 3,
         "update" : 201294849,
         "delete" : 0,
         "getmore" : 0,
         "command" : 551619
    },
    "asserts" : {
         "regular" : 0,
         "warning" : 0,
         "msg" : 0,
         "user" : 1,
         "rollovers" : 0
    },
    "writeBacksQueued" : false,
    "dur" : {
         "commits" : 28,
         "journaledMB" : 0,
         "writeToDataFilesMB" : 0,
         "compression" : 0,
         "commitsInWriteLock" : 0,
         "earlyCommits" : 0,
         "timeMs" : {
              "dt" : 3062,
              "prepLogBuffer" : 0,
              "writeToJournal" : 0,
              "writeToDataFiles" : 0,
              "remapPrivateView" : 0
         }
    },
    "ok" : 1}
    
    db.index.dataSize():29791637704

    db.index.storageSize():33859297120

    db.index.totalSize():45272200048

    db.index.totalIndexSize():11412902928

    db.runCommand(“getCmdLineOpts”):{“argv”:[“/mongod”],“parsed”:{},“ok”:1}


    我的代码片段。我刚刚删除了那些MongoDB连接代码,并将核心保留在这里

    static void fillupDb()
    {
        for (double i = 0; i < 1024 * 1024 * 1024 / 3; i++)
        {
            //Convert the counter i to a 20 bytes of array as KEY
            byte[] prekey = BitConverter.GetBytes(i);
            byte[] key = new byte[20];
            prekey.CopyTo(key, 0);
    
            // Generate a random 100 bytes of VALUE
            byte[] value = getRandomBytes(100);
            put(key, value);
        }
    }
    
    public void put(byte[] key, byte[] value)
    {
        BsonDocument pair = new BsonDocument {
            { "_id", key } /* I am using _id as the index */,
            { "value", value }};
        collection.Save(pair);
    }
    
    static void fillupDb()
    {
    对于(双i=0;i<1024*1024*1024/3;i++)
    {
    //将计数器i转换为20字节数组作为密钥
    byte[]prekey=BitConverter.GetBytes(i);
    字节[]键=新字节[20];
    prekey.CopyTo(键,0);
    //生成随机的100字节值
    字节[]值=getRandomBytes(100);
    put(键、值);
    }
    }
    公共void put(字节[]键,字节[]值)
    {
    BsonDocument对=新的BsonDocument{
    {“_id”,key}/*我使用_id作为索引*/,
    {“value”,value}};
    收集。保存(对);
    }
    
    好吧,首先。如何测量输入数据的大小?键值对可以是两个字符串或一个JSON对象

    此外,每个文档都添加了一些额外的填充,以便通过后续更新促进文档的增长。可以通过db.col.stats().paddingFactor检索平均填充因子

    最后,可能会增加开销的不仅仅是oplog。在_id上总是有一个索引,在您的情况下(因为您的文档非常小),它将在磁盘空间使用方面引入大量开销。除非您禁用它(--nojournal),否则日志也会将相当多的字节添加到总数中


    希望这会有帮助。

    好吧,首先。如何测量输入数据的大小?键值对可以是两个字符串或一个JSON对象

    此外,每个文档都添加了一些额外的填充,以便通过后续更新促进文档的增长。可以通过db.col.stats().paddingFactor检索平均填充因子

    最后,可能会增加开销的不仅仅是oplog。在_id上总是有一个索引,在您的情况下(因为您的文档非常小),它将在磁盘空间使用方面引入大量开销。除非您禁用它(--nojournal),否则日志也会将相当多的字节添加到总数中


    希望这会有所帮助。

    我也愿意打赌,这主要是建立在您的表上的索引。解析它们很便宜,但需要大量的存储空间。是的,如果他存储{u id:..,value:..}对,这将是一个大容量,因为在这种情况下,每个索引项大约是文档本身大小的四分之一(假设100字节的值)。谢谢你的回答。然而,对于索引,我实际上使用了_id(mongodb的内部索引)作为我的键,它是20字节。这意味着,在计算中,我已经包括了指数的大小。此外,我的实验中的键和值都是字节数组。键是20字节,值是100字节。所以,不管怎样,我认为一次插入的数据大小是120字节,对吗?不。你怎么会认为索引包括在内?120字节的文档将在索引b树中生成一个节点/叶。这将是_id值本身和一些较小的开销。虽然很难说它会是20字节或更多(12字节的id和8字节的数据偏移量),但请尝试db.collection.stats().indexSizes和see。我也愿意打赌它主要是建立在表上的索引。解析它们很便宜,但需要大量的存储空间。是的,如果他存储{u id:..,value:..}对,这将是一个大容量,因为在这种情况下,每个索引项大约是文档本身大小的四分之一(假设100字节的值)。谢谢你的回答。H