[MongoDB] aggregate 查询的优化思路

首先从业务角度出发,不必要的筛选条件和粗略的筛选条件会严重影响查询速度,比如 $or 查询和 $in 查询,视情况尽可能去掉。 

程序中打印出查询条件的各部分,有 $match、$group。比如 PHP 中可以通过 var_export()。

由于 aggregate 执行主要是 pipeline 步骤,所以着重需要关注的是 $match 条件。

打印出的数组 json_encode 后可以在 Robo3T 等客户端中作为 aggregate 的条件使用。

关于 aggregate 查询条件的格式,可参考:https://studio3t.com/knowledge-base/articles/build-mongodb-aggregation-queries/

为了方便查看 json 条件格式,可以对json在线格式化,之后使用如 Example1.

aggregate() 后面直接带不了 explain() 方法,为了使用 explain() 方法查看索引使用情况等信息,复制出 $match 的 json 条件 到 find({ }) 中,然后带上 explain() 方法。

查看 explain() 显示的信息 queryPlanner 部分,里面有 winningPlan.stage 状态分析,如 Example2.

常见的 winningPlan.stage 如下:
  COLLSCAN:全表扫描
  IXSCAN      :索引扫描
  FETCH       :根据索引去检索指定document
  更多的可以搜索 mongodb explain 相关信息。

把 COLLSCAN 优化成  IXSCAN 使用索引,此时再看 winningPlan.inputStage.keyPattern 使用的索引字段是哪个。

如果 keyPattern 使用的是低效率的索引可以通过 hint 用法强制指定索引,支持普通查询和聚合查询。

普通查询的 hint 方法: ->find({})->hint({ diff_id: 1 })

聚合查询的 hint 参数:docs.mongodb.com,如 Example3.

Example1.

db.getCollection('diff_detail').aggregate(
[
    {
    "$match": {
        "diff_id": ObjectId('71162dcf17a1f594edcc69bc'),
        "pvalue": {
            "$lt": 0.05
        },
        "vip": {
            "$gt": 1
        },
        "$or": [{
            "fc": {
                "$gt": 1
            }
        }, {
            "fc": {
                "$lt": 1
            }
        }],
        "diff_group": {
            "$in": ["a1_vs_A1", "a2_vs_A2", "a3_vs_A3", "a4_vs_A4", "a5_vs_A5"]
        }
    }
    },
    {
    "$group": {
        "_id": {
            "table_type": "$table_type",
            "diff_group": "$diff_group"
        },
        "count": {
            "$sum": 1
        }
    }
    }
]

);

Example2.

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "xxxdb.diff_detail",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [ 
                {
                    "$or" : [ 
                        {
                            "fc" : {
                                "$lt" : 1.0
                            }
                        }, 
                        {
                            "fc" : {
                                "$gt" : 1.0
                            }
                        }
                    ]
                }, 
                {
                    "diff_id" : {
                        "$eq" : ObjectId("71162dcf17a1f594edcc69bc")
                    }
                }, 
                {
                    "pvalue" : {
                        "$lt" : 0.05
                    }
                }, 
                {
                    "vip" : {
                        "$gt" : 1.0
                    }
                }, 
                {
                    "diff_group" : {
                        "$in" : [ 
                            "a1_vs_A1", 
                            "a2_vs_A2", 
                            "a3_vs_A3", 
                            "a4_vs_A4", 
                            "a5_vs_A5"
                        ]
                    }
                }
            ]
        },
        "queryHash" : "22D09A47",
        "planCacheKey" : "22D09A47",
        "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "$and" : [ 
                    {
                        "$or" : [ 
                            {
                                "fc" : {
                                    "$lt" : 1.0
                                }
                            }, 
                            {
                                "fc" : {
                                    "$gt" : 1.0
                                }
                            }
                        ]
                    }, 
                    {
                        "diff_id" : {
                            "$eq" : ObjectId("71162dcf17a1f594edcc69bc")
                        }
                    }, 
                    {
                        "pvalue" : {
                            "$lt" : 0.05
                        }
                    }, 
                    {
                        "vip" : {
                            "$gt" : 1.0
                        }
                    }, 
                    {
                        "diff_group" : {
                            "$in" : [ 
                                "a1_vs_A1", 
                                "a2_vs_A2", 
                                "a3_vs_A3", 
                                "a4_vs_A4", 
                                "a5_vs_A5"
                            ]
                        }
                    }
                ]
            },
            "direction" : "forward"
        },
        "rejectedPlans" : []
    },
    "serverInfo" : {
        "host" : "mongodb446",
        "port" : 27017,
        "version" : "4.4.1",
        "gitVersion" : "ad91a93a5a31e175f5cbf8c69561e788bbc55ce1"
    },
    "ok" : 1.0
}

Example3.

Link:https://www.cnblogs.com/farwish/p/15379066.html

原文地址:https://www.cnblogs.com/farwish/p/15379066.html