2013-06-12 2 views
0

나는 CIDR의 모음은 다음과 같은 스키마 범위가 있습니다복합 인덱스 쿼리보다 여러

{ bottom: Number 
top: Number 
cidrText: String 
live: Boolean 
hits: Number } 

내가 뭘하려고 오전의 IP가 바닥 + 정상 범위 내에있는 경우 (찾을 수 있습니다 . 다음 내 인덱스는 순간 그 기록에 안타

을 달러 (A $)의 INC 업데이트를 수행

db.tbl.ensureIndex({ bottom: 1, top: 1, live: 1 }); 

하지만 내 쿼리를 실행할 때 - 쿼리의 일부를 다음이 인덱스 및 사용 큰 흠집이있다. 내 서버의 성능에 관한 법률 : 내 쿼리

입니다

:

db.tbl.find({ live: true, top: { $gte: 3266341261 }, bottom: { $lte: 3266341261 } }) 

설명 출력은 다음과 같습니다

{ 
    "cursor" : "BtreeCursor top_1", 
    "isMultiKey" : false, 
    "n" : 0, 
    "nscannedObjects" : 0, 
    "nscanned" : 0, 
    "nscannedObjectsAllPlans" : 0, 
    "nscannedAllPlans" : 7, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "millis" : 0, 
    "indexBounds" : { 
     "top" : [ 
      [ 
       3266341261, 
       1.7976931348623157e+308 
      ] 
     ] 
    }, 
    "server" : "local:27017" 
} 

내가 모두 $ GTE와 $ LTE가 동일하게 사용하는 얻을 수있는 방법이 있나요 색인 - 또는 2 개의 검색어를 실행하고 두 검색어에서 일치하는 행을 찾아야합니까?

편집 나는 기존의 모든 인덱스를 떨어 복합 인덱스를 다시 추가하고 지금은 정확한 경계를 취득하지만, 높은 여전히 ​​nscanned입니다했다.

{ 
    "cursor" : "BtreeCursor bottom_1_top_1_live_1", 
    "isMultiKey" : false, 
    "n" : 0, 
    "nscannedObjects" : 0, 
    "nscanned" : 4748, 
    "nscannedObjectsAllPlans" : 4746, 
    "nscannedAllPlans" : 9494, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "millis" : 15, 
    "indexBounds" : { 
     "bottom" : [ 
      [ 
       -1.7976931348623157e+308, 
       3633904421 
      ] 
     ], 
     "top" : [ 
      [ 
       3633904421, 
       1.7976931348623157e+308 
      ] 
     ], 
     "live" : [ 
      [ 
       true, 
       true 
      ] 
     ] 
    }, 
    "server" : "local27017" 
} 

또한 내 로그에이 얻을 :

warning: ClientCursor::yield can't unlock b/c of recursive lock ns: col.tbl top: { opid: 25701683, active: true, secs_running: 0, op: "query", ns: "tbl", query: { findandmodify: "tbl", query: { live: true, top: { $gte: 1584813140 }, bottom: { $lte: 1584813140 } }, sort: {}, new: 1, remove: 0, upsert: 0, update: { $inc: { hits: 1 } } }, client: "127.0.0.1:39407", desc: "conn581", threadId: "0x497ec940", connectionId: 581, locks: { ^: "w", ^tbl: "W" }, waitingForLock: false, numYields: 0, lockStats: { timeLockedMicros: {}, timeAcquiringMicros: { r: 0, w: 3 } } } 

편집 2

까지 너무 명확 "찾기 매개 변수의 순서"검색어의 순서 생겼한다 이 색인 순서와 일치해야합니다 (at least in 2.4.4). 이 2 개의 쿼리를 실행하면 - 다른 인덱스는 그렇지 않은 인덱스를 사용합니다.

> db.tbl.find({top: {$lte: 1454442030}, bottom: {$gte: 1454442030}}).explain() 
{ 
    "cursor" : "BtreeCursor top_1", 
    "isMultiKey" : false, 
    "n" : 2, 
    "nscannedObjects" : 2271, 
    "nscanned" : 2271, 
    "nscannedObjectsAllPlans" : 6816, 
    "nscannedAllPlans" : 11396, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "millis" : 24, 
    "indexBounds" : { 
     "top" : [ 
      [ 
       -1.7976931348623157e+308, 
       1454442030 
      ] 
     ] 
    }, 
    "server" : "local:27017" 
} 

> db.tbl.find({bottom: {$lte: 1454442030}, top: {$gte: 1454442030}}).explain() 
{ 
    "cursor" : "BtreeCursor bottom_1_top_1_live_1", 
    "isMultiKey" : false, 
    "n" : 2, 
    "nscannedObjects" : 2, 
    "nscanned" : 2080, 
    "nscannedObjectsAllPlans" : 6240, 
    "nscannedAllPlans" : 10400, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "millis" : 23, 
    "indexBounds" : { 
     "bottom" : [ 
      [ 
       -1.7976931348623157e+308, 
       1454442030 
      ] 
     ], 
     "top" : [ 
      [ 
       1454442030, 
       1.7976931348623157e+308 
      ] 
     ], 
     "live" : [ 
      [ 
       { 
        "$minElement" : 1 
       }, 
       { 
        "$maxElement" : 1 
       } 
      ] 
     ] 
    }, 
    "server" : "local:27017" 
} 

감사

마크

+0

같은 질문과 문제는 다음과 같습니다. http://stackoverflow.com/questions/8061022/search-for-a-record-where-a-value-is-between-two-item-fields-in -mongodb – WiredPrairie

+0

'explain' 출력이 이상합니다 - 아무것도 스캔되지 않았습니까? – WiredPrairie

+0

복합 인덱스의 순서와 일치하도록'find' 쿼리를 재정렬 할 수 있습니까? – WiredPrairie

답변

0

경고는이 발견() 쿼리와는 아무 상관이있다.

또한 nscanned가 높지 않아야한다고 생각하지 않는 이유는 무엇입니까?

{bottom : {$ lte : 3266341261}}은 (는) 일치하는 모든 색인 레코드를 확인한 다음 {top : {$ gte : 3266341261}} 필터를 적용해야합니다. explaing()에서 인덱스 경계를 ​​확인하십시오. 예상대로 올바르게 적용됩니다.

다음을 실행할 수 있습니까? 그것은에 가까워 야 { "nscanned"4748}

db.tbl.find({ bottom: { $lte: 3266341261 } }).explain() 
+0

결과는 다음과 같습니다. "nscanned": 4683, 'find()'결과는 "nscanned"입니다. 5317 –

+0

값이 4683이면 원래 질문에 대해 nscanned가 높아야합니다. nscanned는 검색해야하는 총 색인 항목입니다. nscannedObjects와 혼동하지 않는다고 생각합니다. –

1

스캔 인덱스 항목의 수가가 높은 이유 때문에 당신의 복합 인덱스의 키의 선택의 순서이다.인덱스 항목의 순서는 인덱스를 사용할 수있는 쿼리와 쿼리가 검색해야하는 인덱스 항목의 수 모두에 중요합니다.

live=true의 컬렉션에있는 항목의 비율이 매우 낮은 경우 "라이브"를 첫 번째 키로 사용하여 복합 색인을 구성하는 것이 좋습니다. 라이브 = true 인 모든 쿼리는 매우 선택적이다.

데이터 분포 및 쿼리 패턴을 알지 못해 올바른 접근 방식이 무엇인지 알기는 어렵지만 일반적으로 선택적인 키를 가장 먼저 배치하려는 필드의 순서에 대해 선택하는 경우 선택적 것들이 마지막.

관련 문제