1

2 つのフィールドを持つドキュメントを含む MongoDB バージョン 3.0.3 コレクションがあります。

  • 数値の長い ID
  • 60 個の数値 Double の配列。

配列にマルチキー インデックスを作成し、メソッドを使用してインデックスが存在し、マルチキーであることを確認しましたgetIndexInfo()。ただし、配列内の特定のフィールドの 2 つの範囲の交差をクエリすると、コレクションに 1,000,000 のドキュメントがあるにもかかわらず、Mongo はこのインデックスを使用しません。explain()これは、メソッドの出力からわかります。さらに奇妙なことに、 でインデックスの使用を指定するとhint、Mongo は 1,000,000 のドキュメントすべてと 60,000,000 のインデックス エントリをトラバースしますexplain()

次のコードでクエリを作成しています。

BasicDBObject q2 = new BasicDBObject("array.0",new BasicDBObject("$lt",1000.0));
BasicDBObject q1 = new BasicDBObject("array.1",new BasicDBObject("$gte",800.0));
BasicDBObject q_and = new BasicDBObject("$and",Arrays.asList(q1,q2));
dbo = collection.find(q_and).explain();

何かご意見は?

よろしくお願いします。

Explain 出力の要求に応じて:

ヒントを指定しない場合、Explain の出力は次のようになります。

{ "queryPlanner" : 
{ "plannerVersion" : 1 , "namespace" : "local.TestArrays" , "indexFilterSet" : false , "parsedQuery" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "winningPlan" : 
{ "stage" : "COLLSCAN" , "filter" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "direction" : "forward"
} , "rejectedPlans" : [ ]
} , "executionStats" : 
{ "executionSuccess" : true , "nReturned" : 2 , "executionTimeMillis" : 2248 , "totalKeysExamined" : 0 , "totalDocsExamined" : 1000000 , "executionStages" : 
{ "stage" : "COLLSCAN" , "filter" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "nReturned" : 2 , "executionTimeMillisEstimate" : 2190 , "works" : 1000002 , "advanced" : 2 , "needTime" : 999999 , "needFetch" : 0 , "saveState" : 7812 , "restoreState" : 7812 , "isEOF" : 1 , "invalidates" : 0 , "direction" : "forward" , "docsExamined" : 1000000
} , "allPlansExecution" : [ ]
} , "serverInfo" : 
{ "host" : "NYDEVWS0005052" , "port" : 27017 , "version" : "3.0.3" , "gitVersion" : "b40106b36eecd1b4407eb1ad1af6bc60593c6105"
}
}

次のコードで使用するインデックスを指定する場合:

collection.find(q_and).hint("array_1").explain();

説明の出力は次のとおりです。

{ "queryPlanner" : 
{ "plannerVersion" : 1 , "namespace" : "local.TestArrays" , "indexFilterSet" : false , "parsedQuery" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "winningPlan" : 
{ "stage" : "KEEP_MUTATIONS" , "inputStage" : 
{ "stage" : "FETCH" , "filter" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "inputStage" : 
{ "stage" : "IXSCAN" , "keyPattern" : 
{ "array" : 1
} , "indexName" : "array_1" , "isMultiKey" : true , "direction" : "forward" , "indexBounds" : 
{ "array" : [ "[MinKey, MaxKey]"]
}
}
}
} , "rejectedPlans" : [ ]
} , "executionStats" : 
{ "executionSuccess" : true , "nReturned" : 2 , "executionTimeMillis" : 61401 , "totalKeysExamined" : 60000000 , "totalDocsExamined" : 1000000 , "executionStages" : 
{ "stage" : "KEEP_MUTATIONS" , "nReturned" : 2 , "executionTimeMillisEstimate" : 56570 , "works" : 60001744 , "advanced" : 2 , "needTime" : 59999998 , "needFetch" : 1743 , "saveState" : 470130 , "restoreState" : 470130 , "isEOF" : 1 , "invalidates" : 0 , "inputStage" : 
{ "stage" : "FETCH" , "filter" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "nReturned" : 2 , "executionTimeMillisEstimate" : 55620 , "works" : 60001744 , "advanced" : 2 , "needTime" : 59999998 , "needFetch" : 1743 , "saveState" : 470130 , "restoreState" : 470130 , "isEOF" : 1 , "invalidates" : 0 , "docsExamined" : 1000000 , "alreadyHasObj" : 0 , "inputStage" : 
{ "stage" : "IXSCAN" , "nReturned" : 1000000 , "executionTimeMillisEstimate" : 50820 , "works" : 60000000 , "advanced" : 1000000 , "needTime" : 59000000 , "needFetch" : 0 , "saveState" : 470130 , "restoreState" : 470130 , "isEOF" : 1 , "invalidates" : 0 , "keyPattern" : 
{ "array" : 1
} , "indexName" : "array_1" , "isMultiKey" : true , "direction" : "forward" , "indexBounds" : 
{ "array" : [ "[MinKey, MaxKey]"]
} , "keysExamined" : 60000000 , "dupsTested" : 60000000 , "dupsDropped" : 59000000 , "seenInvalidated" : 0 , "matchTested" : 0
}
}
} , "allPlansExecution" : [ ]
} , "serverInfo" : 
{ "host" : "NYDEVWS0005052" , "port" : 27017 , "version" : "3.0.3" , "gitVersion" : "b40106b36eecd1b4407eb1ad1af6bc60593c6105"
}
}
4

2 に答える 2

1

マルチキー インデックスの意味を誤解していました。配列内の位置ごとに個別のインデックスが作成されたと思いました。ただし、さらに読むと、配列に対して単一のインデックスが作成され、ドキュメントのすべてのエントリがその単一のインデックスに入力され、配列の位置が保持されないことがわかります。n9code のアドバイスを受けて、個別のフィールドと各フィールドのインデックスを作成しました。それは期待どおりに機能します。

于 2015-05-27T18:50:20.530 に答える
0

あなたの問題は、配列の特定の要素を照会していることだと思います。そのため、その配列にインデックスがある場合でも、クエリはコレクション全体を明示的にスキャンし、要素0をフェッチして1からarrayマッチングを実行する必要があります。

特定の要素に対して正確に一致を実行する必要がある場合は、それらを配列から取り出して個別のフィールドとして保持し、それらにインデックスを作成することをお勧めします。したがって、これを考慮してください:

{
   ...
   array: [...],
   ex_element_0: "value0",
   ex_element_1: "value0",
   ...
}
于 2015-05-27T14:37:17.053 に答える