2012-06-15 2 views
3

더블 복합 지수가 {a : 1, b : 1} 인 경우 b 만 쿼리하면 인덱스가 사용되지 않는다는 의미가됩니다. 즉, 건너 뛰기 "). 그러나 만 쿼리하면 인덱스가 사용됩니다. {: 1, B : 1, C : 1}하면 "C (즉, 당신이 수에 쿼리 할 때 명령은 인덱스를 사용하는 것을 보여주고 설명의 나 삼중 복합 인덱스 주어진 그러나몽고 트리플 화합물 인덱스

, 건너 뛰기 "b).

어떻게 몽고는 교류에 대한 쿼리 상에 ABC 인덱스를 사용할 수 있으며,이 경우 지수는 얼마나 효과적입니까?

배경 :

내 사용 사례가 가끔 A, B, C에 조회 할 때때로 나는 A, C에 조회 할 것입니다. 이제 a, b, c 중 하나만 색인을 생성해야합니까? 아니면 a, c 및 a, b, c 중 하나를 작성해야합니까?

(그것은 C 좋은 선택과 다중 키 인덱스이기 때문에 B,, C를 A의 인덱스를 만들 수 이해가되지 않습니다.)

답변

2

결론/TL; DR : acc에 종류를 위해, 예를 들어, 평등 또는 불평등에 대한 쿼리가 아닌 경우 지수 b은 '생략'이 될 수 있습니다.

아주 좋은 질문입니다. 불행히도, 나는 정식으로 이것에 대해 더 자세히 대답하는 것을 찾을 수 없었다. 지난 수년간 이러한 쿼리의 성능이 향상되었다고 생각합니다. 따라서이 주제에 대한 오래된 자료는 신뢰할 수 없습니다. 그것은 당신의 인덱스의 선택에 따라 달라집니다 당신이 평등, 불평등 및/또는 종류의 쿼리 여부, 그래서 explain() 당신의 유일한 친구이기 때문에

모든 것은 매우 복잡하지만 여기 내가 찾은 몇 가지 있습니다 :

경고문 : 지금은 실험 결과, 추론 및 추측의 혼합입니다.나는 카일의 유추를 너무 멀리 뻗어있을 수도 있고, 도 완전히 틀릴 수도있다. (내 테스트 결과가 내 추론과 매치하기 때문에 재수가 좋다.)

A의 선택도에 따라 확실하게 A의 지수를 사용할 수 있다는 것은 분명합니다. 'Skipping'B는 까다 롭거나 그렇지 않을 수 있습니다. 나는 성분을 알 수 없기 때문에, 모든 검사해야합니다, 당신은 지금 "샤토"라는 일부 프랑스 요리를 찾아 내게 묻는다면 나는 인덱스 A 사용할 수

French 
    Beef 
     ... 
    Chicken 
     Coq au Vin 
     Roasted Chicken 
    Lamb 
     ... 
    ... 

과 : 이제 Kyle's cookbook example이 비슷한을 유지하자 접시는 A입니다. 반면에 각 카테고리의 요리 목록은 색인 C을 통해 정렬되므로 각 성분 목록에서 "Cha"로 시작하는 문자열 만 살펴 봐야합니다. 50 가지 재료가 있다면, 단 하나가 아닌 50 번의 조회가 필요할 것입니다.하지만 모든 프랑스 요리를 스캔하는 것보다 훨씬 낫습니다! 나는 단지 하나의 컬렉션이 테스트는 그러나 2를 초과 seemd 결코, 아마과 관련이있다 : 내 실험에서

는 수 b에서 고유 값의 수보다 훨씬 작았 다 b -index의 선택도. 당신이 당신에게 모든 프랑스 요리의 알파벳 순으로 정렬 목록을 제공달라고하면

하지만, 나는 문제에있을 것입니다. 이제 C에 대한 색인은 쓸모가 없습니다. 모든 색인 목록을 병합해야합니다. 그렇게하기 위해 모든 요소를 ​​스캔해야 할 것입니다.

이것은 내 테스트에 반영되었습니다. 다음은 간단한 결과입니다. 원래 컬렉션에는 datetimes, int 및 문자열이 있지만 일을 단순하게 유지하려고 했으므로 이제는 모두 int입니다.

nscanned < = 2 * limit 인 쿼리 클래스와 전체 컬렉션 (120K 문서)을 검색해야하는 쿼리가 기본적으로 두 가지입니다. 지수는 {a, b, c}입니다 :

// fast (range query on c while skipping b) 
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}); 
// slow (sorting) 
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "c" : -1}); 
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "b" : -1}); 

// fast (can sort on c if b included in the query) 
> db.Test.find({"a" : 43, "b" : 7887, "c" : { $lte : 45454 }}).sort({ "c" : -1}); 

// fast (older tutorials claim this is slow) 
> db.Test.find({"a" : {$gte : 43}, "c" : { $lte : 45454 }}); 

귀하의 주행 거리에 따라 달라질 수 있습니다.

+0

감사합니다. 이것은 권위있는 참고 자료가 부족하다는 점을 감안할 때 최상의 정보 일 것입니다. 내 특정 경우에 B는 낮은 선택도 열이며 C에서 "시작"쿼리를 수행하고 있습니다. 따라서 내 ABC 인덱스는 AC 쿼리의 AC 인덱스와 거의 비슷하다고 가정합니다. 나는 주행 거리가 변하기 때문에 AC와 ABC 지수를 당분간 같이 볼 수있다. –

+0

C에서 정렬하지 않는 한 AC 색인만큼 좋을 것 같지만' explain()'은 확실히 말할 수 있습니다. 'nscanned'를 주시하십시오.'n'보다 훨씬 커야합니다. – mnemosyn

1

당신은으로 A와 C에 쿼리를 볼 수 있습니다 A를 쿼리하는 특별한 경우 (인덱스가 사용될 경우) 인덱스를 사용하는 것이 전체 문서를로드하는 것보다 효율적입니다.

는 7과 13 사이의 모든 문서를 얻고 싶었다 가정 및 C 5 ~ 당신은 단지에 인덱스가 있다면 8

: 데이터베이스 사이의 문서를 선택하기 위해 인덱스를 사용할 수 7과 13을 사용하지만 C가 5와 8 사이인지 확인하려면 해당 문서도 검색해야합니다.

인덱스가 A, B 및 C 인 경우 데이터베이스는 인덱스를 사용하여 A가 7 - 13 인 문서를 선택할 수 있습니다. C의 값은 이미 인덱스 레코드에 저장되어 있으므로 해당 문서를 검색하지 않고도 해당 문서가 C 기준과 일치하는지 여부를 결정할 수 있습니다. 따라서 더 나은 성능으로 디스크 읽기를 피할 수 있습니다.

+0

다른 말로하면, AC에서 쿼리 할 때 ABC 인덱스가 A 단독 인덱스보다 우수하다는 말입니까? –

+0

문서를 읽을 필요없이 색인 자체에서 원하지 않는 C 값을 필터링 할 수 있기 때문에 더 좋습니다. – Eduardo

+0

-1 @ 에두아르도 나는 당신의 추론을 많이 따르지 않는다고 생각합니다. 인덱스의 C 부분을 어떻게 사용할 수 있습니까? "전체 문서를로드하지 마십시오"라는 색인의 목적을 생각하는 것은 상당히 잘못된 것입니다. 실제로 스캔해야 할 문서 수 (nscan) 측면에서 생각해야합니다. –