有一个非常简单的查询:
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 Hi I / O实例)上运行,需要1.7秒才能完成......
> 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" : ""
}
Collection有大约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 :(得分:0)
响应缓慢是因为嵌入式文档的索引:
> db.users.getIndices()
[
{
"v" : 1,
"key" : {
"likes.id" : 1
},
"ns" : "od.users",
"name" : "likes.id"
}
]
带有likes属性的示例文档:
> 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个嵌入的喜欢文档,这些文档在likes.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" : ""
}
>
因此,如果此数组的大小非常大,似乎在Mongo中的嵌入式文档数组中添加索引会显着降低更新性能。