2017-09-20 3 views
0

수백만 레코드가있는 로그 컬렉션이 있습니다. 새 색인 만들기는 "영원히"걸립니다. 따라서 기존 인덱스를 사용하는 것이 좋습니다.MongoDB가 내 인덱스를 사용하지 않습니다.

이제 특정 오류 코드의 발생 횟수를 확인하고자합니다. 나는이 쿼리를 사용하고, 기능적으로 그것을 잘 작동합니다 :

db.getCollection('logs.res').aggregate([ 
    { 
     $match:{  
      timeStamp: { 
       $gte: new Date('2017-05-01').getTime(), // timeStamp is Number 
       $lt : new Date('2017-05-02').getTime() // of ms since epoch 
      }, 
      '[email protected]': { 
       $ne: null 
      } 
     } 
    }, 
    { 
     $group: { 
      _id: '[email protected]', 
      count: {$sum: 1} 
     } 
    }, 
    { 
     $sort: { count: -1} 
    } 
]); 

문제가 잘 근처에 10 초 동안 단 하루 동안이 작업을 실행하는 데 걸리는입니다. [email protected]_1을 : 나는 다음과 같은 인덱스가 사용되는 것으로 가정했다

{ 
    "timeStamp" : -1, 
    "[email protected]" : 1 
} 

그러나, MongoDB를 어떤 응답 있는지 확인하기 위해 (쿼리와 관련이없는 다른 인덱스) 일부 timeStamp: 1 인덱스를 사용하고, 그 결과 alllllll 스캔 단호 보인다 이 정보가 색인에 있어야하지만 ErrorCode이 첨부 될 수 있습니다. 여기

explain()입니다 :이 속도를 위해 [email protected]_1 인덱스를 사용하는 방법은

enter image description here

  • 있습니까?
  • 이이 색인을 사용하는이 아닌 이유는 무엇입니까? 아마도이 쿼리에서 인덱스가 사용되는 방식을 오해하고 있습니다. OSX에 MongoDB를 3.2.7을 실행

.

참고 : 나는 $ne: null 대신 $empty: true도 시도했습니다. 동일한 결과를 산출하지만 복합 색인을 사용하려면 $empty을 사용할 수 없다고 말하는 사람들도 있습니다. 스택 오버플로에 대한 많은 질문은 오래되었습니다 (mongo 2.x).

답변

2

승리 계획은 CACHED PLAN입니다. 캐시 계획을 지울 수 있습니다.

db.getCollection('logs.res').getPlanCache().clear() 

캐시를 지운 후에도 Mongo는 여전히 잘못된 색인을 사용하고 있습니다. 쿼리 계획을 설정하거나 "힌트"를 사용하여 인덱스를 강제 설정할 수 있습니다.

+0

알다시피, 힌팅은 테스트 용이며 집계 파이프 라인에 대한 인덱스 힌트를 설정할 수 없습니다. – Redsandro

+0

aggreggate 전에 planCacheSetFilter 함수를 사용할 수 있습니다. – Marco

1

일반 mongodb 인덱스는 필드 값과 유형을 모두 사용하여 트리를 작성합니다.

$empty: true 또는 $ne: null과 같은 검색어에는 어떤 유형의 매개 변수도 없으며 이러한 색인을 활용할 수 없습니다. 특수한 경우이며 특별한 sparse index이 필요합니다. 당신의 [email protected]_1 인덱스로 만든 경우

는 :

db.getCollection('logs.res').createIndex(
    { 
     "timeStamp" : -1, 
     "[email protected]" : 1 
    }, 
    { sparse: true } 
) 

이 가장 쿼리를 지원해야한다. 그렇지 않으면 첫 번째 필드 만 사용되기 때문에 [email protected]_1timeStamp_1_module_1_etc 사이에는 큰 차이가 없습니다.

+0

이것은 적합 할 수 있습니다. 그래서 나는 대신'$ nin : [모든 오류 id의 배열 목록]'을 할 수 있을까요? 아니면 항상 쓸모없는 것으로 설정되지 않은 필드에 대한 비 스파 스 색인입니까? – Redsandro

+0

또는 더 나은 :'$ ne : 999999'. 이것은 number 유형의 매개 변수입니다. 그것은 단지 사용되지 않습니다. – Redsandro

+0

그래, 둘 다 인덱스를 사용해야하지만'$ ne : null'과 같은 쿼리가 아닙니다. 두 경우 모두 널 (null)을 갖습니다. 모든 에러 코드를 안다면'$ in : [list]'를 쓸 수 있지만, 예기치 않은 에러 코드가있는 문서를 놓칠 수 있습니다. –