MongoDB为什么多重条件比mysql慢

时间:2019-07-03 05:51:21

标签: mongodb

users馆藏有2000000个文档。

users模式在这里。

MongoDB> db.users.find().limit(1).pretty()
{
    "_id" : ObjectId("5d09e3d6ffe466000e1006e1"),
    "created_at" : ISODate("2019-06-19T07:07:24Z"),
    "updated_at" : ISODate("2019-06-19T07:27:17Z"),
    "user_id" : NumberLong(2141055),
    "nickname" : "john",
    "birthday" : ISODate("1992-08-02T00:00:00Z"),
    "gender" : "M",
    "region" : "US",
    "is_fake" : false,
    "is_block" : false,
    "is_out" : false,
    "is_introduce_disable" : true,
    "final_score" : 40
}

我必须通过具有多种过滤条件的distinct()提取user_id

过滤条件

  • gte <生日
  • gte
  • is_out:否
  • is_fake:false
  • is_block:false
  • is_introduce_disable:false
  • 性别:“ M”或“ F”

所以我首先创建索引。

[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.users"
    },
    {
        "v" : 2,
        "unique" : true,
        "key" : {
            "user_id" : 1
        },
        "name" : "user_id_1",
        "ns" : "test.users"
    },
    {
        "v" : 2,
        "key" : {
            "nickname" : 1
        },
        "name" : "nickname_1",
        "ns" : "test.users"
    },
    {
        "v" : 2,
        "key" : {
            "birthday" : 1
        },
        "name" : "birthday_1",
        "ns" : "test.users"
    },
    {
        "v" : 2,
        "key" : {
            "is_out" : 1,
            "is_fake" : 1,
            "is_block" : 1,
            "is_introduce_disable" : 1,
            "birthday" : 1,
            "gender" : 1,
            "final_score" : 1
        },
        "name" : "is_out_1_is_fake_1_is_block_1_is_introduce_disable_1_birthday_1_gender_1_final_score_1",
        "ns" : "test.users"
    }
]

并运行distinct()。

db.users.explain("executionStats").distinct(
    "user_id",
    {   "birthday": {
        "$lte": ISODate("1992-06-08T00:00:00.000Z"),
        "$gte": ISODate("1985-06-08T00:00:00.000Z")
    },
    "final_score": {
        "$lte": 51.4, 
        "$gte": 10.73
    },
    "is_out": false, 
    "is_fake": false, 
    "is_block": false, 
    "is_introduce_disable": false,
    "gender": "M"}
)

显然,这需要500毫秒。

所以我通过`explain()检查查询。

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.users",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [
                {
                    "gender" : {
                        "$eq" : "M"
                    }
                },
                {
                    "is_block" : {
                        "$eq" : false
                    }
                },
                {
                    "is_fake" : {
                        "$eq" : false
                    }
                },
                {
                    "is_introduce_disable" : {
                        "$eq" : false
                    }
                },
                {
                    "is_out" : {
                        "$eq" : false
                    }
                },
                {
                    "birthday" : {
                        "$lte" : ISODate("1992-06-08T00:00:00Z")
                    }
                },
                {
                    "final_score" : {
                        "$lte" : 51.4
                    }
                },
                {
                    "birthday" : {
                        "$gte" : ISODate("1985-06-08T00:00:00Z")
                    }
                },
                {
                    "final_score" : {
                        "$gte" : 10.73
                    }
                }
            ]
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "is_out" : 1,
                    "is_fake" : 1,
                    "is_block" : 1,
                    "is_introduce_disable" : 1,
                    "birthday" : 1,
                    "gender" : 1,
                    "final_score" : 1
                },
                "indexName" : "is_out_1_is_fake_1_is_block_1_is_introduce_disable_1_birthday_1_gender_1_final_score_1",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "is_out" : [ ],
                    "is_fake" : [ ],
                    "is_block" : [ ],
                    "is_introduce_disable" : [ ],
                    "birthday" : [ ],
                    "gender" : [ ],
                    "final_score" : [ ]
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "is_out" : [
                        "[false, false]"
                    ],
                    "is_fake" : [
                        "[false, false]"
                    ],
                    "is_block" : [
                        "[false, false]"
                    ],
                    "is_introduce_disable" : [
                        "[false, false]"
                    ],
                    "birthday" : [
                        "[new Date(487036800000), new Date(707961600000)]"
                    ],
                    "gender" : [
                        "[\"M\", \"M\"]"
                    ],
                    "final_score" : [
                        "[10.73, 51.4]"
                    ]
                }
            }
        },
        "rejectedPlans" : [
            {
                "stage" : "FETCH",
                "filter" : {
                    "$and" : [
                        {
                            "gender" : {
                                "$eq" : "M"
                            }
                        },
                        {
                            "is_block" : {
                                "$eq" : false
                            }
                        },
                        {
                            "is_fake" : {
                                "$eq" : false
                            }
                        },
                        {
                            "is_introduce_disable" : {
                                "$eq" : false
                            }
                        },
                        {
                            "is_out" : {
                                "$eq" : false
                            }
                        },
                        {
                            "final_score" : {
                                "$lte" : 51.4
                            }
                        },
                        {
                            "final_score" : {
                                "$gte" : 10.73
                            }
                        }
                    ]
                },
                "inputStage" : {
                    "stage" : "IXSCAN",
                    "keyPattern" : {
                        "birthday" : 1
                    },
                    "indexName" : "birthday_1",
                    "isMultiKey" : false,
                    "multiKeyPaths" : {
                        "birthday" : [ ]
                    },
                    "isUnique" : false,
                    "isSparse" : false,
                    "isPartial" : false,
                    "indexVersion" : 2,
                    "direction" : "forward",
                    "indexBounds" : {
                        "birthday" : [
                            "[new Date(487036800000), new Date(707961600000)]"
                        ]
                    }
                }
            }
        ]
    },
    "executionStats" : {
        "executionSuccess" : true,
        "nReturned" : 219815,
        "executionTimeMillis" : 488,
        "totalKeysExamined" : 224093,
        "totalDocsExamined" : 219815,
        "executionStages" : {
            "stage" : "FETCH",
            "nReturned" : 219815,
            "executionTimeMillisEstimate" : 39,
            "works" : 224093,
            "advanced" : 219815,
            "needTime" : 4277,
            "needYield" : 0,
            "saveState" : 1752,
            "restoreState" : 1752,
            "isEOF" : 1,
            "invalidates" : 0,
            "docsExamined" : 219815,
            "alreadyHasObj" : 0,
            "inputStage" : {
                "stage" : "IXSCAN",
                "nReturned" : 219815,
                "executionTimeMillisEstimate" : 17,
                "works" : 224093,
                "advanced" : 219815,
                "needTime" : 4277,
                "needYield" : 0,
                "saveState" : 1752,
                "restoreState" : 1752,
                "isEOF" : 1,
                "invalidates" : 0,
                "keyPattern" : {
                    "is_out" : 1,
                    "is_fake" : 1,
                    "is_block" : 1,
                    "is_introduce_disable" : 1,
                    "birthday" : 1,
                    "gender" : 1,
                    "final_score" : 1
                },
                "indexName" : "is_out_1_is_fake_1_is_block_1_is_introduce_disable_1_birthday_1_gender_1_final_score_1",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "is_out" : [ ],
                    "is_fake" : [ ],
                    "is_block" : [ ],
                    "is_introduce_disable" : [ ],
                    "birthday" : [ ],
                    "gender" : [ ],
                    "final_score" : [ ]
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "is_out" : [
                        "[false, false]"
                    ],
                    "is_fake" : [
                        "[false, false]"
                    ],
                    "is_block" : [
                        "[false, false]"
                    ],
                    "is_introduce_disable" : [
                        "[false, false]"
                    ],
                    "birthday" : [
                        "[new Date(487036800000), new Date(707961600000)]"
                    ],
                    "gender" : [
                        "[\"M\", \"M\"]"
                    ],
                    "final_score" : [
                        "[10.73, 51.4]"
                    ]
                },
                "keysExamined" : 224093,
                "seeks" : 4278,
                "dupsTested" : 0,
                "dupsDropped" : 0,
                "seenInvalidated" : 0
            }
        }
    },
    "serverInfo" : {
        "host" : "localhost",
        "port" : 27017,
        "version" : "4.0.10",
        "gitVersion" : "c389e7f69f637f7a1ac3cc9fae843b635f20b766"
    },
    "ok" : 1,
    "operationTime" : Timestamp(1562132746, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1562132746, 1),
        "signature" : {
            "hash" : BinData(0,"KZsayJye5mbXpHU9tB0i5RnWa9I="),
            "keyId" : NumberLong("6706752768855506945")
        }
    }
}

executionStats中,

        "nReturned" : 219815,
        "executionTimeMillis" : 488,
        "totalKeysExamined" : 224093,
        "totalDocsExamined" : 219815,

似乎没问题。因为nReturnedtotalKeysExamined之间没有太大区别。

您知道这需要将近488ms。但是在mysql中,它需要30毫秒。 (相同的环境)

问题

  1. 为什么在多条件搜索中MongoDB比MySQL慢?

  2. winningPlansrejectedPlans之间的确切区别是什么?

  3. 我的索引配置是否存在任何问题?

  4. 我的查询有任何建议吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

如果正在检查任何文档,则意味着它无法完全根据索引回答问题(在这种情况下,这是因为user_id不在其使用的索引中)。