1. 程式人生 > >MongoDB 效能優化之分頁查詢

MongoDB 效能優化之分頁查詢

最常見的分頁採用的是skip+limit這種組合方式,這種方式對付小資料倒也可以,但是對付上幾百上千萬的大資料,只能力不從心。通過如下思路改善,可以大大提高查詢速度:條件查詢+排序+限制返回記錄。邊查詢,邊排序,排序之後,抽取第一次分頁中的最後一條記錄,作為第二次分頁的條件,進行條件查詢,以此類推.... 下面通過一個例子演示一下: 1.準備資料
>for(var i = 0 ;i < 2000000;i++){db.user.save({"index":i,"name":"zhangsan"+i,"age":(i+10)%100});}
>db.user.count();
2.採用skip+limit方式查詢 查詢以zhangsan2開頭的,並按照index倒敘的第100~109條資料
> db.user.find({name:/^zhangsan2/}).sort({"index":-1}).skip(100).limit(10).explain();
{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 10,
        "nscannedObjects" : 2000000,
        "nscanned" : 2000000,
        "nscannedObjectsAllPlans" : 2000000,
        "nscannedAllPlans" : 2000000,
        "scanAndOrder" : true,
        "indexOnly" : false,
        "nYields" : 3,
        "nChunkSkips" : 0,
        "millis" : 2223,
        "indexBounds" : {

        },
        "server" : "100.205:27017"
}
可以看到查詢一次需要2223ms。 3.查詢下一頁優化處理 當時使用上面方法,查詢110~119條時,依舊耗時2530ms
> db.user.find({name:/^zhangsan2/}).sort({"index":-1}).skip(110).limit(10).explain();
{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 10,
        "nscannedObjects" : 2000000,
        "nscanned" : 2000000,
        "nscannedObjectsAllPlans" : 2000000,
        "nscannedAllPlans" : 2000000,
        "scanAndOrder" : true,
        "indexOnly" : false,
        "nYields" : 3,
        "nChunkSkips" : 0,
        "millis" : 2530,
        "indexBounds" : {

        },
        "server" : "100.205:27017"
}
下面我們通過程式改善一下上面下一頁的查詢,根據第一次100查詢,我們知道index的最小值為299890,由於是按照index的倒敘查詢,所以下一頁的資料為index小於299890的後續10條,查詢如下:
> db.user.find({name:/^zhangsan2/,index:{"$lt":299890}}).sort({"index":-1}).limit(10).explain();
{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 10,
        "nscannedObjects" : 2000000,
        "nscanned" : 2000000,
        "nscannedObjectsAllPlans" : 2000000,
        "nscannedAllPlans" : 2000000,
        "scanAndOrder" : true,
        "indexOnly" : false,
        "nYields" : 1,
        "nChunkSkips" : 0,
        "millis" : 1523,
        "indexBounds" : {

        },
        "server" : "100.205:27017"
}
比較一下與上面的查詢下一頁的效率有顯著的提高,當資料越大的情況下,效果會更明顯。 參考文章: