2012-04-18 3 views
7

모음 이벤트에는 userId와 이벤트 배열이 있습니다. 배열의 각 요소는 포함 된 문서입니다. 예 :mongodb - 날짜의 색인이 사용되지 않습니다.

db.events.find({ events : { $elemMatch: { "eventId" : 201, 
"eventDate" : {$gt : new Date(1231657163876) } } } } ).explain() 

쿼리 계획 "events.eventDate"에 대한 색인이 때 사용되는 것을 보여줍니다 : 지난 30 일 동안 생성 된 이벤트 tofind 아래와 같은 쿼리를 사용

{ 
    "_id" : ObjectId("4f8f48cf5f0d23945a4068ca"), 
    "events" : [ 
      { 
        "eventType" : "profile-updated", 
        "eventId" : "247266", 
        "eventDate" : ISODate("1938-04-27T23:05:51.451Z"), 
      }, 
      { 
        "eventType" : "login", 
        "eventId" : "64531", 
        "eventDate" : ISODate("1948-05-15T23:11:37.413Z"), 
      } 
    ], 
    "userId" : "junit-19568842", 

}

테스트 데이터는 (20의 주위에) 적은 수의 이벤트를 포함

{ 
    "cursor" : "BtreeCursor events.eventDate_1", 
    "nscanned" : 0, 
    "nscannedObjects" : 0, 
    "n" : 0, 
    "millis" : 0, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "isMultiKey" : true, 
    "indexOnly" : false, 
    "indexBounds" : { 
      "events.eventDate" : [ 
        [ 
          ISODate("2009-01-11T06:59:23.876Z"), 
          ISODate("292278995-01--2147483647T07:12:56.808Z") 
        ] 
      ] 
    } 

}

012 (500 정도) 사건의 수가 많은 경우에는 3,516,

은, 인덱스가 사용되지 않습니다

{ 
    "cursor" : "BasicCursor", 
    "nscanned" : 4, 
    "nscannedObjects" : 4, 
    "n" : 0, 
    "millis" : 0, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "isMultiKey" : false, 
    "indexOnly" : false, 
    "indexBounds" : { 

    } 

} 많은 이벤트가있을 때 왜 인덱스가 사용되지 않는

? 많은 이벤트가있을 때 MongoDB는 인덱스를 사용하는 것보다 모든 항목을 스캔하는 것이 효율적이라는 것을 알 수 있습니까?

+0

0 밀리 초를 반환하는 쿼리에서 최적화 프로그램이 인덱스를 사용하지 않는다고 불평하십니까? :) –

+0

위의 Explain 출력은 테스트 콜렉션에서 나온 것입니다. 약 2 천만 건의 문서로 질의는 약 8 초가 걸렸습니다. – dsatish

+0

컬렉션의 문서 중 상당 부분을 쿼리하는 경우 이와 같은 범위 쿼리는 느려질 수 있습니다. 인덱스를 사용하여 속도를 비교하도록 힌트를 사용할 수는 있지만 인덱스 스캔을 수행하는 것과 마찬가지로 속도가 느릴 것이라고 생각합니다. 힌트의 유무와 관계없이 프로덕션 데이터의 설명을 게시해야합니다. 문제는 일치하는 문서가 수백만 개가 발견되면 문서를 검사하는 데 시간이 걸릴 것입니다. –

답변

11

MongoDB의 쿼리 최적화 프로그램은 특별한 방식으로 작동합니다. 특정 쿼리 계획의 비용을 계산하는 대신 사용 가능한 모든 계획을 시작합니다. 먼저 반환되는 것이 최적의 것으로 간주되며 앞으로 사용됩니다.

응용 프로그램이 커지고 데이터가 커지고 변경되며 최적의 계획이 어느 시점에서 최적이되지 않을 수 있습니다. 따라서 mongo는 쿼리 선택 프로세스를 매번 반복합니다.

이 구체적인 경우에는 기본 스캔이 가장 효율적이었습니다.

링크 : 인덱스 "events.eventDate"를 사용하여 강제로 $ 힌트를 사용 http://www.mongodb.org/display/DOCS/Query+Optimizer

2

의 nscannedObjects 인덱스 O/w 이상이다.

의사 코드 인덱스를 사용하여 다음의 기준에 일치 지수

for(all entries in index matching the criteria) { 
    get user object and scan to see if the eventId criteria is met 
} 

모든 항목 -> 각 이벤트는 인덱스 항목이다. 따라서 색인의 항목 수는 사용자 수보다 많습니다. 네 개의 사용자 개체와 기준에 일치하는 총 7 개의 이벤트가 있다고 가정하면 사용자 개체는 7 번 스캔됩니다 (루프가 7 번 실행 됨). 색인이 스캔되지 않으면 모든 4 개의 사용자 객체가 한 번만 검사됩니다. 따라서 인덱스를 사용하면 사용자 객체가 스캔되는 횟수가 인덱스를 사용하지 않을 때보 다 많습니다. 이 말이 맞습니까?

db.events.find({ events : { $elemMatch: { "eventId" : 201, 
"eventDate" : {$gt : new Date(1231657163876) } } } } ) 
._addSpecial("$hint",{"events.eventDate":1}).explain() 

{ 
    "cursor" : "BasicCursor", 
    "nscanned" : 7, 
    "nscannedObjects" : 7, 
    "n" : 0, 
    "millis" : 0, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "isMultiKey" : false, 
    "indexOnly" : false, 
    "indexBounds" : { 

} 
관련 문제