23
回答
求大神指点(有奖):MongoDB表有7000多万条数据,现在更新速度异常的慢!
华为云实践训练营,热门技术免费实践!>>>   
MongoDB表(items集合)有7000多万条数据,现在更新异常的慢。感觉差不多1秒钟只能更新1-5次,异常的慢! (我的实际需求是每天要更新5000万次左右!)

> db.items.count()
70866908

> db.items.stats()
{
        "ns" : "shops_items.items",
        "count" : 70866908,
        "size" : 23675466304,
        "avgObjSize" : 334.083523215095,
        "storageSize" : 26476834672,
        "numExtents" : 33,
        "nindexes" : 4,
        "lastExtentSize" : 2146426864,
        "paddingFactor" : 1.9960000003695433,
        "systemFlags" : 1,
        "userFlags" : 0,
        "totalIndexSize" : 14688412928,
        "indexSizes" : {
                "_id_" : 2299410064,
                "item_id_1" : 2570787856,
                "shop_id_1" : 3433290448,
                "sales_url_1" : 6384924560
        },
        "ok" : 1
}

每天需要更新数据,插入新增数据。程序执行的操作是update(采用upsert=true模式)。

求助大神,如何破解?

问题解决有报酬!

赛钛客(Saitek)美加狮 Mad Catz R.A.T.3 游戏鼠标一只,市场价350元。(不限于此)


PS:之前测试过如果只Insert不Update速度可以达到1000-2000次/秒。


2014-04-23补充:

下面几行是MongoDB的日志,可以看出更新一条记录差不多就要花0.4秒的时间啊!

Mon Apr 21 05:00:01.526 [conn8] update shops_items.items query: { item_id: 38143873013 } update: { $set: { shop_id: 61043531, update_time: new Date(1398038400000), ... item_id: 38143873013 } } nscanned:1 nupdated:1 keyUpdates:0 locks(micros) w:418 478ms


Mon Apr 21 05:00:01.832 [conn8] update shops_items.items query: { item_id: 26097404556 } update: { $set: { shop_id: 104973686, update_time: new Date(1398038400000), ... item_id: 26097404556 } } nscanned:1 nupdated:1 keyUpdates:1 locks(micros) w:627 214ms

Mon Apr 21 05:00:03.298 [conn8] update shops_items.items query: { item_id: 18141302220 } update: { $set: { shop_id: 67539387, update_time: new Date(1398038400000)... item_id: 18141302220 } } nscanned:1 nupdated:1 keyUpdates:0 locks(micros) w:294 702ms

举报
共有23个答案 最后回答: 4年前

首先呢,你的mongo的这个db光索引的大小就是十几个G,再加上热数据,你们跑mongo的机器的内存是多少呢,内存的大小应该是大于索引+热数据的,另外你们跑mongo的机器的磁盘是什么呢?如果只是普通磁盘的话,大量数据要到穿透到磁盘的话,会造成很多的随机寻址,这个性能本身就是很差的,再加上磁盘频繁的随机读写,达到你们现在的情况,一点也不稀罕,给的建议就是加大内存,关闭机器Numa,换成ssd或者是flash卡

--- 共有 4 条评论 ---
周明岐回复 @鲲鹏Web数据采集 : 你们用的是物理机跑的嘛?如果是物理机的话,一定要关闭机器的numa,否则也会影响mongo的性能,虽说是放在内存,但是本身也是有持久化的,这个跟mysql其实很像的,重启不太会影响这个 4年前 回复
西安鲲之鹏回复 @周明岐 : 我采用的是MongoDB的默认配置。怎么配置才能把索引都放到内存中呢?另外,如果真的都放到内存中,没有持久化的话,机器重启了索引不是没有了? 4年前 回复
周明岐回复 @鲲鹏Web数据采集 : 剩余18G绝对的不正常,正常情况下mongo的内存占用应该是索引大小+热数据大小,否则性能肯定会受影响,会频繁的穿透到磁盘随机读写,严重影响性能 4年前 回复
西安鲲之鹏机器物理内存是24GB,目前看剩余18GB左右。 是普通硬盘,用iostat查看,我的%util才22%。 4年前 回复

没接触过这么多数据,也没接触过MongoDB。。。

搜到个问题,不知道管用不:http://stackoverflow.com/questions/16103193/mongodb-findandmodify-extremely-slow

上面这个帖子的最后一行回复。

--- 共有 1 条评论 ---
西安鲲之鹏多谢,我试试 db.runCommand( {collMod: "items", usePowerOf2Sizes : true }) 4年前 回复

如果没有使用ObjectId作为检索条件,这么多数据的表更新必须使用索引,ps;insert只是追加,不检索数据,大部分情况下不影响性能

--- 共有 1 条评论 ---
西安鲲之鹏更新时候用的就是索引item_id(在indexSizes中可看到)。 4年前 回复

引用来自“jQer”的评论

explain()看看

> db.items.find({'item_id': 21089495147}).explain()
{
        "cursor" : "BtreeCursor item_id_1",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 1,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 1,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "item_id" : [
                        [
                                21089495147,
                                21089495147
                        ]
                ]
        },
        "server" : "ubuntu:27017"
}
似乎没有什么有用的信息。
顶部