2013-02-13 49 views
1

有一个非常简单的查询:MogoDB更新以超过1秒

db.users.update({"_id" : ObjectId("50710913a6427bfa2600000c") },{$inc: {"points" : 5}}) 

有一个指数的“点”字段:

db.users.getIndices() 
[ 
    { 
     "v" : 1, 
     "key" : { 
      "_id" : 1 
     }, 
     "ns" : "od.users", 
     "name" : "_id_" 
    }, 
    { 
     "v" : 1, 
     "key" : { 
      "points" : 1 
     }, 
     "ns" : "od.users", 
     "name" : "points" 
    }, 
    { 
     "v" : 1, 
     "key" : { 
      "lastActivity" : -1 
     }, 
     "ns" : "od.users", 
     "name" : "lastActivity" 
    } 
] 

一些指标省略清晰。

我正在上的MongoDB 2.2.3查询,空闲数据库和快速的机器(Amazon EC2的嗨I/O实例)上,它需要超过170秒才能完成......

> db.system.profile.find({ns:"od.users"}).sort({$natural:-1}).limit(1).pretty() 
{ 
    "ts" : ISODate("2013-02-13T20:44:52.858Z"), 
    "op" : "update", 
    "ns" : "od.users", 
    "query" : { 
     "_id" : ObjectId("50710913a6427bfa2600000c") 
    }, 
    "updateobj" : { 
     "$inc" : { 
      "points" : 5 
     } 
    }, 
    "nscanned" : 1, 
    "nupdated" : 1, 
    "keyUpdates" : 1, 
    "numYield" : 0, 
    "lockStats" : { 
     "timeLockedMicros" : { 
      "r" : NumberLong(0), 
      "w" : NumberLong(1747665) 
     }, 
     "timeAcquiringMicros" : { 
      "r" : NumberLong(0), 
      "w" : NumberLong(5964) 
     } 
    }, 
    "millis" : 1747, 
    "client" : "127.0.0.1", 
    "user" : "" 
} 

一旦我删除索引,查询完成在任何时间:

> db.system.profile.find({ns:"od.users"}).sort({$natural:-1}).limit(1).pretty() 
{ 
    "ts" : ISODate("2013-02-13T20:47:03.032Z"), 
    "op" : "update", 
    "ns" : "od.users", 
    "query" : { 
     "_id" : ObjectId("50710913a6427bfa2600000c") 
    }, 
    "updateobj" : { 
     "$inc" : { 
      "points" : 5 
     } 
    }, 
    "idhack" : true, 
    "nupdated" : 1, 
    "keyUpdates" : 0, 
    "numYield" : 0, 
    "lockStats" : { 
     "timeLockedMicros" : { 
      "r" : NumberLong(0), 
      "w" : NumberLong(153) 
     }, 
     "timeAcquiringMicros" : { 
      "r" : NumberLong(0), 
      "w" : NumberLong(5) 
     } 
    }, 
    "millis" : 0, 
    "client" : "127.0.0.1", 
    "user" : "" 
} 

收藏有大约71K的文件:

> db.users.stats() 
{ 
    "ns" : "od.users", 
    "count" : 71236, 
    "size" : 2389260264, 
    "avgObjSize" : 33540.06771856926, 
    "storageSize" : 3987849216, 
    "numExtents" : 20, 
    "nindexes" : 23, 
    "lastExtentSize" : 1039589376, 
    "paddingFactor" : 1.0000000002382583, 
    "systemFlags" : 1, 
    "userFlags" : 0, 
    "totalIndexSize" : 1120676144, 
    "indexSizes" : { 
     "_id_" : 3343984, 
     "email" : 4578560, 
     "country_1" : 2649024, 
     "wPopularity" : 3278576, 
     "wRandom" : 2869776, 
     "wPhoto" : 2959712, 
     "username_1" : 2657200, 
     "tsRegistered" : 2976064, 
     "likes.id" : 483610400, 
     "dmForCnt_1" : 2861600, 
     "wPopularity3" : 573660864, 
     "tags" : 4611264, 
     "status" : 3311280, 
     "birthday" : 2959712, 
     "gender" : 3008768, 
     "points" : 2869776, 
     "employee" : 2174816, 
     "manualSubscription" : 2338336, 
     "facebookID_1" : 3916304, 
     "facebookID" : 4161584, 
     "lastActivity" : 2796192, 
     "isFraud" : 1537088, 
     "settingsDailyMatch" : 1545264 
    }, 
    "ok" : 1 
} 

是否认为更新索引字段需要这么长时间?我错过了什么吗?

更新:

我注意到只有大于100K的文档才有这个问题。其他文件正在迅速更新。

+0

这台机器使用多少内存?我知道你说这是一个71k的用户数据库(小),但内存不足?如果指数不适合记忆,你可能会遇到这样的问题。我可以通过您的users.stats()查询查看您的索引大小总计超过1 Gb。 – 2013-02-13 21:04:43

+0

总存储器大小是60G,设备处于闲置状态: #自由-m 总使用的无共享缓冲器缓存 号负责:62020 61727 292 0 20 58743 -/+缓冲器/高速缓存:2964 59055 交换:511 0 511 – 2013-02-13 21:15:17

+0

你可以每次在不同的用户上运行更新吗?您可能会看到第二次缓存益处 – 2013-02-13 21:17:30

回答

0

反应缓慢,是因为在嵌入文档的索引:与喜欢

> db.users.getIndices() 
[ 
    { 
     "v" : 1, 
     "key" : { 
      "likes.id" : 1 
     }, 
     "ns" : "od.users", 
     "name" : "likes.id" 
    } 
] 

实施例的文档属性:

> obj = db.users.findOne({"_id" : ObjectId("50710913a6427bfa2600000c")}) 
> Object.bsonsize(obj) 
532162 
> obj.likes.length 
4770 
> obj.likes[0] 
{ 
    "id" : "103128829727364", 
    "name" : "Jennifer Lopez", 
    "category" : "Musician/band", 
    "hidden" : false, 
} 

所以有4770嵌入喜欢的文件,并且这些上喜欢索引.id属性。

当我运行此文件上的更新,即使它不触及喜欢:

> db.users.update({"_id" : ObjectId("50710913a6427bfa2600000c") },{$addToSet: {"otherPhotos" : "holipiuouiouioiuoi1"}}) 

需要很长的:

> db.system.profile.find({op:"update"}).sort({ts:-1}).limit(1).pretty() 
{ 
    "ts" : ISODate("2013-02-20T08:59:30.707Z"), 
    "op" : "update", 
    "ns" : "od.users", 
    "query" : { 
     "_id" : ObjectId("50710913a6427bfa2600000c") 
    }, 
    "updateobj" : { 
     "$addToSet" : { 
      "otherPhotos" : "holipiuouiouioiuoi1" 
     } 
    }, 
    "idhack" : true, 
    "nupdated" : 1, 
    "keyUpdates" : 0, 
    "numYield" : 0, 
    "lockStats" : { 
     "timeLockedMicros" : { 
      "r" : NumberLong(0), 
      "w" : NumberLong(1752759) 
     }, 
     "timeAcquiringMicros" : { 
      "r" : NumberLong(0), 
      "w" : NumberLong(83) 
     } 
    }, 
    "millis" : 1752, 
    "client" : "127.0.0.1", 
    "user" : "" 
} 

但是当我删除索引它的工作原理炽烈快:

> db.users.dropIndex("likes.id") 
{ "nIndexesWas" : 2, "ok" : 1 } 
> db.users.update({"_id" : ObjectId("50710913a6427bfa2600000c") },{$addToSet: {"otherPhotos" : "holipiuouiouioiuoi12hkjhkjhkjhkjhkjhkjhkj"}}) 
> db.system.profile.find({op:"update"}).sort({ts:-1}).limit(1).pretty() 
{ 
    "ts" : ISODate("2013-02-20T09:02:13.747Z"), 
    "op" : "update", 
    "ns" : "od.users", 
    "query" : { 
     "_id" : ObjectId("50710913a6427bfa2600000c") 
    }, 
    "updateobj" : { 
     "$addToSet" : { 
      "otherPhotos" : "holipiuouiouioiuoi12hkjhkjhkjhkjhkjhkjhkj" 
     } 
    }, 
    "idhack" : true, 
    "nupdated" : 1, 
    "keyUpdates" : 0, 
    "numYield" : 0, 
    "lockStats" : { 
     "timeLockedMicros" : { 
      "r" : NumberLong(0), 
      "w" : NumberLong(1137) 
     }, 
     "timeAcquiringMicros" : { 
      "r" : NumberLong(0), 
      "w" : NumberLong(5) 
     } 
    }, 
    "millis" : 1, 
    "client" : "127.0.0.1", 
    "user" : "" 
} 

一旦违规索引已被删除,我能够添加索引的“点”和原现在查询响应时间仅为1毫秒:

> db.users.ensureIndex({points:1}) 
> db.users.getIndices() 
[ 
    { 
     "v" : 1, 
     "key" : { 
      "_id" : 1 
     }, 
     "ns" : "od.users", 
     "name" : "_id_" 
    }, 
    { 
     "v" : 1, 
     "key" : { 
      "points" : 1 
     }, 
     "ns" : "od.users", 
     "name" : "points_1" 
    } 
] 
> db.users.update({"_id" : ObjectId("50710913a6427bfa2600000c") },{$inc: {"points" : 5}}) 
> db.system.profile.find({op:"update"}).sort({ts:-1}).limit(1).pretty() 
{ 
    "ts" : ISODate("2013-02-20T09:12:37.664Z"), 
    "op" : "update", 
    "ns" : "od.users", 
    "query" : { 
     "_id" : ObjectId("50710913a6427bfa2600000c") 
    }, 
    "updateobj" : { 
     "$inc" : { 
      "points" : 5 
     } 
    }, 
    "nscanned" : 1, 
    "nupdated" : 1, 
    "keyUpdates" : 1, 
    "numYield" : 0, 
    "lockStats" : { 
     "timeLockedMicros" : { 
      "r" : NumberLong(0), 
      "w" : NumberLong(1225) 
     }, 
     "timeAcquiringMicros" : { 
      "r" : NumberLong(0), 
      "w" : NumberLong(4) 
     } 
    }, 
    "millis" : 1, 
    "client" : "127.0.0.1", 
    "user" : "" 
} 
> 

如此看来,嵌入文档中蒙戈阵列上添加索引可以显著降低更新性能,如果这个数组的大小可以相当大。