2016-08-17 3 views
2

mongodb에서 indice를 사용하여 쿼리를 작성해야합니다. 실제 사례가 최소한의 경우를 보여줍니다.

나는 흐르는 데이터 수집을 다음 있습니다 :

devsrv(mongod-3.0.4) test> db.teste.find() 
{ 
    "_id": ObjectId("57b324c341aaa4b930ef3b92"), 
    "a": 1, 
    "b": 1 
} 
{ 
    "_id": ObjectId("57b324c941aaa4b930ef3b93"), 
    "a": 1, 
    "b": 2 
} 
{ 
    "_id": ObjectId("57b324cd41aaa4b930ef3b94"), 
    "a": 1, 
    "b": 3 
} 
{ 
    "_id": ObjectId("57b324d141aaa4b930ef3b95"), 
    "a": 1, 
    "b": 4 
} 
{ 
    "_id": ObjectId("57b324d541aaa4b930ef3b96"), 
    "a": 1, 
    "b": 5 
} 
{ 
    "_id": ObjectId("57b324da41aaa4b930ef3b97"), 
    "a": 1, 
    "b": 6 
} 
{ 
    "_id": ObjectId("57b324df41aaa4b930ef3b98"), 
    "a": 1, 
    "b": 7 
} 
{ 
    "_id": ObjectId("57b324e441aaa4b930ef3b99"), 
    "a": 1, 
    "b": 8 
} 
{ 
    "_id": ObjectId("57b324f341aaa4b930ef3b9a"), 
    "a": 1, 
    "b": "" 
} 
{ 
    "_id": ObjectId("57b324f641aaa4b930ef3b9b"), 
    "a": 1, 
    "b": " " 
} 
{ 
    "_id": ObjectId("57b324fc41aaa4b930ef3b9c"), 
    "a": 1, 
    "b": null 
} 
{ 
    "_id": ObjectId("57b3250341aaa4b930ef3b9d"), 
    "a": 1 
} 
{ 
    "_id": ObjectId("57b46ace41aaa4b930ef3b9e"), 
    "a": 2 
} 

그리고이 다음 인덱스 :

devsrv(mongod-3.0.4) test> db.teste.getIndexes() 
[ 
    { 
    "v": 1, 
    "key": { 
     "_id": 1 
    }, 
    "name": "_id_", 
    "ns": "test.teste" 
    }, 
    { 
    "v": 1, 
    "key": { 
     "a": 1, 
     "b": 1 
    }, 
    "name": "a_1_b_1", 
    "ns": "test.teste" 
    }, 
    { 
    "v": 1, 
    "key": { 
     "b": 1 
    }, 
    "name": "b_1", 
    "ns": "test.teste" 
    } 
] 

내가 같은 쿼리를 만들 필요가있다이 :

devsrv(mongod-3.0.4) test> db.teste.find({$or:[{"b":null},{"b":""},{"b":" "},{"b":{$lt:3}}],"a":1}).explain("executionStats") 
{ 
    "queryPlanner": { 
    "plannerVersion": 1, 
    "namespace": "test.teste", 
    "indexFilterSet": false, 
    "parsedQuery": { 
     "$and": [ 
     { 
      "$or": [ 
      { 
       "b": { 
       "$eq": null 
       } 
      }, 
      { 
       "b": { 
       "$eq": "" 
       } 
      }, 
      { 
       "b": { 
       "$eq": " " 
       } 
      }, 
      { 
       "b": { 
       "$lt": 3 
       } 
      } 
      ] 
     }, 
     { 
      "a": { 
      "$eq": 1 
      } 
     } 
     ] 
    }, 
    "winningPlan": { 
     "stage": "FETCH", 
     "filter": { 
     "a": { 
      "$eq": 1 
     } 
     }, 
     "inputStage": { 
     "stage": "FETCH", 
     "filter": { 
      "$or": [ 
      { 
       "b": { 
       "$eq": null 
       } 
      }, 
      { 
       "b": { 
       "$eq": "" 
       } 
      }, 
      { 
       "b": { 
       "$eq": " " 
       } 
      }, 
      { 
       "b": { 
       "$lt": 3 
       } 
      } 
      ] 
     }, 
     "inputStage": { 
      "stage": "IXSCAN", 
      "keyPattern": { 
      "b": 1 
      }, 
      "indexName": "b_1", 
      "isMultiKey": false, 
      "direction": "forward", 
      "indexBounds": { 
      "b": [ 
       "[null, null]", 
       "[-inf.0, 3.0)", 
       "[\"\", \"\"]", 
       "[\" \", \" \"]" 
      ] 
      } 
     } 
     } 
    }, 
    "rejectedPlans": [ 
     { 
     "stage": "FETCH", 
     "filter": { 
      "$or": [ 
      { 
       "b": { 
       "$eq": null 
       } 
      }, 
      { 
       "b": { 
       "$eq": "" 
       } 
      }, 
      { 
       "b": { 
       "$eq": " " 
       } 
      }, 
      { 
       "b": { 
       "$lt": 3 
       } 
      } 
      ] 
     }, 
     "inputStage": { 
      "stage": "IXSCAN", 
      "keyPattern": { 
      "a": 1, 
      "b": 1 
      }, 
      "indexName": "a_1_b_1", 
      "isMultiKey": false, 
      "direction": "forward", 
      "indexBounds": { 
      "a": [ 
       "[1.0, 1.0]" 
      ], 
      "b": [ 
       "[MinKey, MaxKey]" 
      ] 
      } 
     } 
     } 
    ] 
    }, 
    "executionStats": { 
    "executionSuccess": true, 
    "nReturned": 6, 
    "executionTimeMillis": 0, 
    "totalKeysExamined": 8, 
    "totalDocsExamined": 14, 
    "executionStages": { 
     "stage": "FETCH", 
     "filter": { 
     "a": { 
      "$eq": 1 
     } 
     }, 
     "nReturned": 6, 
     "executionTimeMillisEstimate": 0, 
     "works": 10, 
     "advanced": 6, 
     "needTime": 2, 
     "needFetch": 0, 
     "saveState": 0, 
     "restoreState": 0, 
     "isEOF": 1, 
     "invalidates": 0, 
     "docsExamined": 7, 
     "alreadyHasObj": 7, 
     "inputStage": { 
     "stage": "FETCH", 
     "filter": { 
      "$or": [ 
      { 
       "b": { 
       "$eq": null 
       } 
      }, 
      { 
       "b": { 
       "$eq": "" 
       } 
      }, 
      { 
       "b": { 
       "$eq": " " 
       } 
      }, 
      { 
       "b": { 
       "$lt": 3 
       } 
      } 
      ] 
     }, 
     "nReturned": 7, 
     "executionTimeMillisEstimate": 0, 
     "works": 8, 
     "advanced": 7, 
     "needTime": 1, 
     "needFetch": 0, 
     "saveState": 0, 
     "restoreState": 0, 
     "isEOF": 1, 
     "invalidates": 0, 
     "docsExamined": 7, 
     "alreadyHasObj": 0, 
     "inputStage": { 
      "stage": "IXSCAN", 
      "nReturned": 7, 
      "executionTimeMillisEstimate": 0, 
      "works": 8, 
      "advanced": 7, 
      "needTime": 1, 
      "needFetch": 0, 
      "saveState": 0, 
      "restoreState": 0, 
      "isEOF": 1, 
      "invalidates": 0, 
      "keyPattern": { 
      "b": 1 
      }, 
      "indexName": "b_1", 
      "isMultiKey": false, 
      "direction": "forward", 
      "indexBounds": { 
      "b": [ 
       "[null, null]", 
       "[-inf.0, 3.0)", 
       "[\"\", \"\"]", 
       "[\" \", \" \"]" 
      ] 
      }, 
      "keysExamined": 8, 
      "dupsTested": 0, 
      "dupsDropped": 0, 
      "seenInvalidated": 0, 
      "matchTested": 0 
     } 
     } 
    } 
    }, 
    "serverInfo": { 
    "host": "devsrv", 
    "port": 27017, 
    "version": "3.0.4", 
    "gitVersion": "0481c958daeb2969800511e7475dc66986fa9ed5" 
    }, 
    "ok": 1 
} 

그러나 MongoDB는 두 개의 인덱스를 함께 사용하지 않습니다.

+0

누구나 mongo가 두 개의 인덱스를 사용하도록 강제하는 방법을 알고 있습니까? –

답변

0

$or은 효과적으로 별도의 쿼리이므로 각 용어가 사용하고자하는 인덱스와 일치하도록 쿼리를 구조화하는 데 도움이됩니다. 각 $or 용어 내부 a: 1 가동부 수단이 경우 :

db.teste.find({ 
    $or:[ 
    {a: 1, b: null}, 
    {a: 1, b: ""}, 
    {a: 1, b: " "}, 
    {a: 1, b: {$lt: 3}} 
    ]}).explain('executionStats') 

설명 출력 a_1_b_1이 쿼리에 사용되는 것을 나타낸다.

하지만 당신은 하나에 처음 세 개의 용어를 결합 $in를 사용하여 좀 더이 문제를 단순화 할 수 있습니다 :

db.teste.find({ 
    $or:[ 
    {a: 1, b: {$in: [null, "", " "]}}, 
    {a: 1, b: {$lt: 3}} 
    ]}).explain('executionStats') 

이 또한 a_1_b_1 인덱스를 사용 할 수 있습니다.

+0

실제 매개 변수 a를 두 번 사용하지 마십시오.이 매개 변수는 쿼리에서 가져온 것입니다. –

0

코드는 쿼리 최적화 프로그램은 모든 적절한 인덱스와 쿼리의 실제 성능을 측정하여 가장 효율적인 쿼리를 선택로

db.teste.explain("executionStats").find({a: 1, 
             $or:[{b: null}, 
               {b: ""}, 
               {b: " "}, 
               {b: {$lt:3}}] 
             }).hint({a: 1, b: 1}) 

hint 명령에주의한다.

+0

매우 도움이 될 수 있습니다. 감사합니다. –

+0

@DimiAntoniVargas 문제를 해결하는 해답을 수락하는 것이 좋습니다 : – BVengerov

관련 문제