2017-02-21 1 views
2

私はmongo 3.2.9インストールを使用していくつかのライブデータの調査を行っています。主な要点は、文書内のデータが欠落しているレコードの周りにいくつかの詳細を見つけることでした。しかし、私が実行していたクエリは、robomongoとコンパスでタイムアウトしていました。

私は300万を超えるレコードを含むコレクション(foo)を持っています。私はこれは私がモンゴで焼成していたクエリで、barIdを持っていないすべてのレコードを探しています:

db.foo.find({barId:{$exists:true}}).explain(true) 

モンゴからrobomongoやコンパスでから、この実行計画である(その回シェル)

MongoDB Enterprise > db.foo.find({barId:{$exists:true}}).explain(true) 
{ 
    "queryPlanner" : { 
    "plannerVersion" : 1, 
    "namespace" : "myDatabase01.foo", 
    "indexFilterSet" : false, 
    "parsedQuery" : { 
     "barId" : { 
     "$exists" : true 
     } 
    }, 
    "winningPlan" : { 
     "stage" : "FETCH", 
     "filter" : { 
     "barId" : { 
      "$exists" : true 
     } 
     }, 
     "inputStage" : { 
     "stage" : "IXSCAN", 
     "keyPattern" : { 
      "barId" : 1 
     }, 
     "indexName" : "barId_1", 
     "isMultiKey" : false, 
     "isUnique" : false, 
     "isSparse" : false, 
     "isPartial" : false, 
     "indexVersion" : 1, 
     "direction" : "forward", 
     "indexBounds" : { 
      "barId" : [ 
      "[MinKey, MaxKey]" 
      ] 
     } 
     } 
    }, 
    "rejectedPlans" : [ ] 
    }, 
    "executionStats" : { 
    "executionSuccess" : true, 
    "nReturned" : 2, 
    "executionTimeMillis" : 154716, 
    "totalKeysExamined" : 3361040, 
    "totalDocsExamined" : 3361040, 
    "executionStages" : { 
     "stage" : "FETCH", 
     "filter" : { 
     "barId" : { 
      "$exists" : true 
     } 
     }, 
     "nReturned" : 2, 
     "executionTimeMillisEstimate" : 152060, 
     "works" : 3361041, 
     "advanced" : 2, 
     "needTime" : 3361038, 
     "needYield" : 0, 
     "saveState" : 27619, 
     "restoreState" : 27619, 
     "isEOF" : 1, 
     "invalidates" : 0, 
     "docsExamined" : 3361040, 
     "alreadyHasObj" : 0, 
     "inputStage" : { 
     "stage" : "IXSCAN", 
     "nReturned" : 3361040, 
     "executionTimeMillisEstimate" : 1260, 
     "works" : 3361041, 
     "advanced" : 3361040, 
     "needTime" : 0, 
     "needYield" : 0, 
     "saveState" : 27619, 
     "restoreState" : 27619, 
     "isEOF" : 1, 
     "invalidates" : 0, 
     "keyPattern" : { 
      "barId" : 1 
     }, 
     "indexName" : "barId_1", 
     "isMultiKey" : false, 
     "isUnique" : false, 
     "isSparse" : false, 
     "isPartial" : false, 
     "indexVersion" : 1, 
     "direction" : "forward", 
     "indexBounds" : { 
      "barId" : [ 
      "[MinKey, MaxKey]" 
      ] 
     }, 
     "keysExamined" : 3361040, 
     "dupsTested" : 0, 
     "dupsDropped" : 0, 
     "seenInvalidated" : 0 
     } 
    }, 
    "allPlansExecution" : [ ] 
    }, 
    "serverInfo" : { 
    "host" : "myLinuxMachine", 
    "port" : 8080, 
    "version" : "3.2.9", 
    "gitVersion" : "22ec9e93b40c85fc7cae7d56e7d6a02fd811088c" 
    }, 
    "ok" : 1 
} 

それはその私のbarId_1インデックスを使用してのように見えるが、同時にそのはすべての3つの万レコードだけ返すように2

をスキャンする時に、私は類似したクエリを実行したのではなくよりもフィールドの存在を探して0より大きいidsを探しました(すべて)

MongoDB Enterprise > db.foo.find({barId:{$gt:"0"}}).explain(true) 
{ 
    "queryPlanner" : { 
    "plannerVersion" : 1, 
    "namespace" : "myDatabase01.foo", 
    "indexFilterSet" : false, 
    "parsedQuery" : { 
     "barId" : { 
     "$gt" : "0" 
     } 
    }, 
    "winningPlan" : { 
     "stage" : "FETCH", 
     "inputStage" : { 
     "stage" : "IXSCAN", 
     "keyPattern" : { 
      "barId" : 1 
     }, 
     "indexName" : "barId_1", 
     "isMultiKey" : false, 
     "isUnique" : false, 
     "isSparse" : false, 
     "isPartial" : false, 
     "indexVersion" : 1, 
     "direction" : "forward", 
     "indexBounds" : { 
      "barId" : [ 
      "(\"0\", {})" 
      ] 
     } 
     } 
    }, 
    "rejectedPlans" : [ ] 
    }, 
    "executionStats" : { 
    "executionSuccess" : true, 
    "nReturned" : 2, 
    "executionTimeMillis" : 54, 
    "totalKeysExamined" : 2, 
    "totalDocsExamined" : 2, 
    "executionStages" : { 
     "stage" : "FETCH", 
     "nReturned" : 2, 
     "executionTimeMillisEstimate" : 10, 
     "works" : 3, 
     "advanced" : 2, 
     "needTime" : 0, 
     "needYield" : 0, 
     "saveState" : 0, 
     "restoreState" : 0, 
     "isEOF" : 1, 
     "invalidates" : 0, 
     "docsExamined" : 2, 
     "alreadyHasObj" : 0, 
     "inputStage" : { 
     "stage" : "IXSCAN", 
     "nReturned" : 2, 
     "executionTimeMillisEstimate" : 10, 
     "works" : 3, 
     "advanced" : 2, 
     "needTime" : 0, 
     "needYield" : 0, 
     "saveState" : 0, 
     "restoreState" : 0, 
     "isEOF" : 1, 
     "invalidates" : 0, 
     "keyPattern" : { 
      "barId" : 1 
     }, 
     "indexName" : "barId_1", 
     "isMultiKey" : false, 
     "isUnique" : false, 
     "isSparse" : false, 
     "isPartial" : false, 
     "indexVersion" : 1, 
     "direction" : "forward", 
     "indexBounds" : { 
      "barId" : [ 
      "(\"1\", {})" 
      ] 
     }, 
     "keysExamined" : 2, 
     "dupsTested" : 0, 
     "dupsDropped" : 0, 
     "seenInvalidated" : 0 
     } 
    }, 
    "allPlansExecution" : [ ] 
    }, 
    "serverInfo" : { 
    "host" : "myLinuxMachine", 
    "port" : 8080, 
    "version" : "3.2.9", 
    "gitVersion" : "22ec9e93b40c85fc7cae7d56e7d6a02fd811088c" 
    }, 
    "ok" : 1 
} 

これは、再びbarId_1のインデックススキャンを行いました。それは2を返す2レコードをスキャンしました。

完全性のためにここでは2つのレコードがあり、他の300万はサイズと構成が非常に似ています。もちろん

MongoDB Enterprise > db.foo.find({barId:{$gt:"0"}}) 
{ 
    "_id" : "00002f5d-ee4a-4996-bb27-b54ea84df777", "createdDate" : ISODate("2016-11-16T02:26:48.500Z"), "createdBy" : "Exporter", "lastModifiedDate" : ISODate("2016-11-16T02:26:48.500Z"), "lastModifiedBy" : "Exporter", "rolePlayed" : "LA", "roleType" : "T", "oId" : [ "d7316944-62ed-48dc-8ee4-e3bad8c58b10" ], "barId" : "e45b3160-bbb4-24e5-82b3-ad0c28329555", "cId" : "dcc29053-7a1f-439e-9536-fb4e44ff8a51", "timestamp" : "2017-02-20T16:23:15.795Z" 
} 
{ 
    "_id" : "00002f5d-ee4a-4996-bb27-b54ea84df888", "createdDate" : ISODate("2016-11-16T02:26:48.500Z"), "createdBy" : "Exporter", "lastModifiedDate" : ISODate("2016-11-16T02:26:48.500Z"), "lastModifiedBy" : "Exporter", "rolePlayed" : "LA", "roleType" : "T", "oId" : [ "d7316944-62ed-48dc-8ee4-e3bad8c58b10" ], "barId" : "e45b3160-bbb4-24e5-82b3-ad0c28329555", "cId" : "dcc29053-7a1f-439e-9536-fb4e44ff8a51", "timestamp" : "2017-02-20T16:23:15.795Z" 
} 

私はいくつかの周りグーグルで行われ、句が存在するが、多くのスレッドで、私はこれが固定されて読んだとのインデックスを一緒に使用して問題があるように使用されていることがわかりました。それは...ですか?また、フィールドの存在を探すときにインデックスの '正しい'使用を強制するために、$ exists節ではなく、以下のハックを使用することができます。

MongoDB Enterprise > db.foo.find({barId:{$ne:null}}).explain(true) 
{ 
    "queryPlanner" : { 
    "plannerVersion" : 1, 
    "namespace" : "myDatabase01.foo", 
    "indexFilterSet" : false, 
    "parsedQuery" : { 
     "$not" : { 
     "barId" : { 
      "$eq" : null 
     } 
     } 
    }, 
    "winningPlan" : { 
     "stage" : "FETCH", 
     "filter" : { 
     "$not" : { 
      "barId" : { 
      "$eq" : null 
      } 
     } 
     }, 
     "inputStage" : { 
     "stage" : "IXSCAN", 
     "keyPattern" : { 
      "barId" : 1 
     }, 
     "indexName" : "barId_1", 
     "isMultiKey" : false, 
     "isUnique" : false, 
     "isSparse" : false, 
     "isPartial" : false, 
     "indexVersion" : 1, 
     "direction" : "forward", 
     "indexBounds" : { 
      "barId" : [ 
      "[MinKey, null)", 
      "(null, MaxKey]" 
      ] 
     } 
     } 
    }, 
    "rejectedPlans" : [ ] 
    }, 
    "executionStats" : { 
    "executionSuccess" : true, 
    "nReturned" : 2, 
    "executionTimeMillis" : 57, 
    "totalKeysExamined" : 3, 
    "totalDocsExamined" : 2, 
    "executionStages" : { 
     "stage" : "FETCH", 
     "filter" : { 
     "$not" : { 
      "barId" : { 
      "$eq" : null 
      } 
     } 
     }, 
     "nReturned" : 2, 
     "executionTimeMillisEstimate" : 10, 
     "works" : 4, 
     "advanced" : 2, 
     "needTime" : 1, 
     "needYield" : 0, 
     "saveState" : 0, 
     "restoreState" : 0, 
     "isEOF" : 1, 
     "invalidates" : 0, 
     "docsExamined" : 2, 
     "alreadyHasObj" : 0, 
     "inputStage" : { 
     "stage" : "IXSCAN", 
     "nReturned" : 2, 
     "executionTimeMillisEstimate" : 10, 
     "works" : 4, 
     "advanced" : 2, 
     "needTime" : 1, 
     "needYield" : 0, 
     "saveState" : 0, 
     "restoreState" : 0, 
     "isEOF" : 1, 
     "invalidates" : 0, 
     "keyPattern" : { 
      "barId" : 1 
     }, 
     "indexName" : "barId_1", 
     "isMultiKey" : false, 
     "isUnique" : false, 
     "isSparse" : false, 
     "isPartial" : false, 
     "indexVersion" : 1, 
     "direction" : "forward", 
     "indexBounds" : { 
      "barId" : [ 
      "[MinKey, null)", 
      "(null, MaxKey]" 
      ] 
     }, 
     "keysExamined" : 3, 
     "dupsTested" : 0, 
     "dupsDropped" : 0, 
     "seenInvalidated" : 0 
     } 
    }, 
    "allPlansExecution" : [ ] 
    }, 
    "serverInfo" : { 
    "host" : "myLinuxMachine", 
    "port" : 8080, 
    "version" : "3.2.9", 
    "gitVersion" : "22ec9e93b40c85fc7cae7d56e7d6a02fd811088c" 
    }, 
    "ok" : 1 
} 

これは、2つのドキュメントのみがスキャンされ、2つのドキュメントのみが返されます。

私の質問はこうです。 クエリに$を使用する必要がありますか?ライブプロダクションアプリケーションで使用するのに適していますか?答えが「いいえ」の場合、最初に$ exist句が存在するのはなぜですか?

mongoのインストールには間違いがあり、インデックスが何らかの形で考えられない可能性が常にあります。どんな光でも大歓迎ですが、今のところ私は$ ne:nullハックに固執しています。

答えて

2

あなたはbarIdフィールドのpartial index(推奨)またはスパースインデックスを使用する必要があります。これは完全に働いた

db.foo.createIndex(
    { barId: 1 }, 
    { partialFilterExpression: { barId: { $exists: true } } } 
) 
+0

感謝。提案されたインデックスを追加することで、barIdを実行するのにかかる時間が短縮されました。{$ exists:true}クエリは10の係数で実行されます。インデックスの違いの理由を本当に心配しました。なぜこのようなすべてのインデックスを作成しないのですか? – Damo

関連する問題