mongodb利用索引對find結果排序(sort)


mongodb利用索引對find結果排序(sort)

最近線上有個接口超時報警,排查發現是查詢MongoDB的時候比較慢(平均耗時1s以上)。文檔結構很簡單:

{
    "_id" : NumberLong(1214789),
    "created_at" : ISODate("2019-02-21T16:08:44.337Z"),
    "updated_at" : ISODate("2019-02-21T16:08:44.337Z"),
    "cid" : 158865,
    "uid" : NumberLong(1024654707),
    "object_id" : "",
    "random" : 163595854,
    "participation_num" : 1
}

已有索引:

{"_id":1}
{"uid":1}
{"cid":1}
{"cid":1,"uid":1}

接口里的查詢轉換成查詢語句為:

db.record.find({
    "cid":158865,
    "is_del": {
        "$ne": true
    }
}).sort({"_id": -1}).limit(10)

數據量100W+,不小,但是對MongoDB來說應該也不算大。

想當然的覺得:已經有cid索引,那么find時走索引應該查起來很快,排序的話,_id也是有索引的,應該不會出現問題啊。后經老大指點,MongoDB的索引應該和mysql一樣只能用一個(事實上2.6版本開始mongo是可以一個查詢使用多個索引的)。

既然是只能用一個索引,那當然想着把sort里的字段也加一起弄一個復合索引:

{"cid":1,"cid":-1}

加上索引后這里explain里可以看到:

        "winningPlan" : {
            "stage" : "FETCH",
            "filter" : {
                "$not" : {
                    "is_del" : {
                        "$eq" : true
                    }
                }
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "cid" : 1,
                    "_id" : -1
                },
                "indexName" : "cid_id",
                "isMultiKey" : false,
                "direction" : "forward",
                "indexBounds" : {
                    "cid" : [ 
                        "[158865.0, 158865.0]"
                    ],
                    "_id" : [ 
                        "[MaxKey, MinKey]"
                    ]
                }
            }
        }

這里查詢出來的實際上就直接是排好序的了

這里總結下mongo的索引一些要注意的地方:

{
    "_id":1111,
    "a":2222,
    "b":3333
}

有如下三個索引:

{"_id":1}
{"a":1}

當使用如下查詢時,在數據量不同時,mongo選擇的查詢方案是不同的:

db.testdoc.find({"a":2222}).sort({"_id":-1}).limit(10)

當數據量少時,會使用{"_a":1}索引,並進行內存排序,當數據量大時,會使用{"_id":1}索引,這個時候find里的a並沒有用到索引,所以最終是會掃描所有文檔,速度非常慢(上面線上接口慢其實也是這樣的情況).

  • 索引里的排序順序要和sort里的完全一致或完全相反:{"a":-1,"b":1}能用於{"a":-1,"b":1}{"a":1,"b":-1}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM