定期的な表現の問題により型のマッチングのモンゴデータベースCPU占有率($正規表現)が発生したら

ある日、CPU使用率の多くを監視するためのmongoデータベースが高く、ビットをチェックし、次の文は、によるものであることがわかりました。

db.example_collection.find({ "idField":{ "$正規表現": "123456789012345678"}、 "日付フィールド":{ "$正規表現": "2019年10月10日"}})


通常、これはたまたま、私の最初の反応は、この文は再び全表スキャンになりますたびに、その結​​果、インデックス、関連分野の欠如です。


しかし、私は説明()ステートメントを使用して解析し、二つのフィールドがidField上に関与発見され、日付フィールドがインデックス化され、そして文はインデックスを使用することもあります。()の結果を次のように説明します。

mgset-11111111:PRIMARY> db.example_collection.find({ "idField":{ "$正規表現": "123456789012345678"}、 "日付フィールド":{ "$正規表現": "2019年10月10日"}})。説明( "queryPlanner")
{
        "queryPlanner":{
                "plannerVersion":1、
                "名前空間": "example_db.example_collection"、
                "indexFilterSet":偽
                、"parsedQuery":{
                        "$および":[
                                {
                                        "idField":{
                                                "$正規表現": "123456789012345678"
                                        }
                                }、
                                {
                                        "日付フィールド":{
                                                "$正規表現": "2019年10月10日"
                                        }
                                }
                        ]
                }、
                "winningPlan":{
                        "段階": "FETCH"、
                        "inputStage":{
                                "ステージ": " IXSCAN "、
                                「フィルタ":{
                                        "$と":[
                                                {
                                                        "idField":{
                                                                "$正規表現": "123456789012345678"
                                                        }
                                                }、
                                                {
                                                        "日付フィールド":{
                                                                "$正規表現": "2019年10月10日"
                                                        }
                                                }
                                        ]
                                }、
                                "keyPattern":{
                                        "idField":1、
                                        "日付フィールド":1
                                }、
                                "INDEXNAME": " idField_1_dateField_1 "、
                                "isMultiKey":偽、
                                "multiKeyPaths":{
                                        "idField":[]、
                                        "日付フィールド":[]
                                }、
                                "isUnique":偽、
                                "isSparse" :偽、
                                "isPartial":偽、
                                "indexVersion」:2、
                                "方向": "前方"、
                                "indexBounds":{
                                        "idField":[
                                                "[\" \ "{})"、
                                                "[/ 123456789012345678 /、/ 123456789012345678 /]"
                                        ]、
                                        "日付フィールド":[
                                                「[ \ "\"、{})」、
                                                "[/ 10分の2019/10 /、/ 10分の2019/10 /]"
                                        ]
                                }
                        }
                }、
                "rejectedPlans":[]
        }、
        "OK":1
}


ビューは、この文は800〜900msを実行することを発見し、むしろ遅かったログをモンゴ。CPUの監査データベース、あるいは他の限り、この文は毎秒少し高い同時実行であるとして、CPUがすぐに満たされる多くの場合を除きます。


検索した後、発見は、正規表現の問題である可能性があります。これは、ステートメントはないが、出力フィールド「に()ステートメントのインデックスを使用するが、説明であることが判明indexBounds、」ステートメントが実行されたときに所望の索引範囲スキャンを示します。上記の出力は、私はまだそれをそのインデックスの範囲を理解していないことを、真実を伝えるために。idField、日付フィールド両方のフィールドの上記のステートメントは、私はそれが実際にクエリステートメントの効率を改善していないインデックスで、その結果、全体のインデックスツリーをスキャンするべきであると思い、正規表現のマッチング正常でした。


私は、日付フィールドは、通常の試合、ライン上のプレーンテキスト一致の必要はありませんこれらの二つのフィールド、idFieldを見つけ、データベース内のデータを見ました。後は削除してから、その結果を分析するために定期的に$の正規表現マッチング操作はこれです:

mgset-11111111:PRIMARY> db.example_collection.find({ "idField" : "123456789012345678", "dateField" : "2019/10/10"}).explain("queryPlanner")
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "example_db.example_collection",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "$and" : [
                                {
                                        "idField" : {
                                                "$eq" : "123456789012345678"
                                        }
                                },
                                {
                                        "dateField" : {
                                                "$eq" : "2019/10/10"
                                        }
                                }
                        ]
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "idField" : 1,
                                        "dateField" : 1
                                },
                                "indexName" : "idField_1_dateField_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "idField" : [ ],
                                        "dateField" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "idField" : [
                                                "[\"123456789012345678\", \"123456789012345678\"]"
                                        ],
                                        "dateField" : [
                                                "[\"2019/10/10\", \"2019/10/10\"]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "ok" : 1
}


可以看到,仍然使用到了索引,并且索引扫描范围是仅限于一个值的。


后来跟开发人员确认了下,该语句确实没必要使用正则匹配,就让他把正则匹配去掉了。之后就没有再出现问题了,mongo慢日志中也未再出现该语句。

おすすめ

転載: blog.51cto.com/techsnail/2449305