2013-02-13 79 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" : "" 
} 
> 

如此看來,嵌入文檔中蒙戈陣列上添加索引可以顯著降低更新性能,如果這個數組的大小可以相當大。