ある日、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慢日志中也未再出现该语句。