概要
MongoDB 3.0 からexplain
の結果が大きく変わりました。
スロークエリを調べる上で、インデックスの使用、外部ソートの使用などをどこで確認するかをまとめてみました。
環境
- Ubuntu 14.04
- MongoDB 3.0.4
大まかな構造(全体)
> db.users.find({name: "ユーザ001"}).explain() { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "コレクション", "indexFilterSet" : false, "parsedQuery" : { // findの中のクエリ }, "winningPlan" : { // 採用されたインデクス }, "rejectedPlans" : [ // インデクスとして使えるが、今回は使われなかったインデクス ] }, "serverInfo" : { // サーバ情報 }, "ok" : 1 }
上記のようにqueryPlanner
に詳細が出てきます。
主にwinningPlan
を見ます。
大まかな構造(プラン)
winningPlanの中身を以下に表示します。
"stage": "FETCH", "inputStage": { "stage": "IXSCAN", "filter": { "name": {} }, "keyPattern": { "name": 1 }, "indexName": "name_1", "isMultiKey": false, "direction": "forward", "indexBounds": { "name": [ "[\"\", {})", "[/ユーザ001/, /ユーザ001/]" ] } }
Mongo3.0ではstage
というものでインデクスを使用しているか判断します。
よく見るstage
は以下です。
種類 | 意味 |
---|---|
COLLSCAN | インデクスを用いないフルスキャン |
IXSCAN | インデクスを用いたスキャン |
FETCH | コレクションからドキュメントを取得 |
SHARD_MERGE | シャードから結果を集約 |
LIMIT | limitで件数制限 |
簡単に言ってしまえば、IXSCAN
であればインデクスを使っています。
なので最低限そこは注意しましょう。
またstage
はクエリによってはネストした親子関係になります。
上の例の場合は「インデクスでスキャン後、コレクションからドキュメント取得」なので、
FETCH └IXSCAN
となってます。
これに更に.limit()
をつければ「インデクスでスキャン後、コレクションからドキュメント取得し、件数を制限」するので
LIMIT └FETCH └IXSCAN
となります。
応用
「外部ソートを使用しているか」、「クエリプランは最適か」など、更に詳細を調べたい場合はexecutionStats
を付けます。
> db.users.find({name: "ユーザ001"}).explain("executionStats")
先ほどのフィールドに加えてより詳細なフィールドが表示されます。
簡単のためよく見るフィールドのみ以下に書きます。
"executionStats" : { ..., "nReturned" : 1, "totalKeysExamined" : 1, "totalDocsExamined" : 1, ..., },
上記の意味の説明と、旧バージョンを比較した表が以下です。
3.0 | 2.6 | 説明 |
---|---|---|
totalKeysExamined | nscanned | スキャンされたドキュメントの数 |
totalDocsExamined | nscannedObjects | コレクションから取得したドキュメント数 covered queriesなら 0 になる |
nReturned | n | 最終的に返却したドキュメント数 |
stage: "SORT" | scanAndOrder: true | 外部ソートを使用 |
IXSCAN の親stageがFETCH でない |
indexOnly: true | Covered Queries |
これらをチェックすれば基本的に大丈夫です。