2012-07-11 5 views
2

두 개의 동일한 인덱스가 동일한 쿼리를 실행하는 동일한 테이블에 2 개의 동일한 (배정 밀도) 열이 있습니다. 아직 한 사람은 다른 사람보다 10 배 빨리 달린다. 이게 뭐야? 28ms의PostgreSQL 인덱스 쿼리 속도 불일치

1) SELECT MIN("reports"."longitude") AS min_id FROM "reports" WHERE (area2 = 18) 

2) SELECT MIN("reports"."latitude") AS min_id FROM "reports" WHERE (area2 = 18) 

1 실행하고 여기>이 300ms

2 개 실행은 '설명'은 다음과 같습니다
1)

Result (cost=6.07..6.08 rows=1 width=0)" 
InitPlan 1 (returns $0)" 
    -> Limit (cost=0.00..6.07 rows=1 width=8)" 
     -> Index Scan using longitude on reports (cost=0.00..139617.49 rows=22983 width=8)" 
      Index Cond: (longitude IS NOT NULL)" 
      Filter: (area2 = 18)" 

2)

Result (cost=5.95..5.96 rows=1 width=0)" 
InitPlan 1 (returns $0)" 
    -> Limit (cost=0.00..5.95 rows=1 width=8)" 
     -> Index Scan using latitude on reports (cost=0.00..136754.07 rows=22983 width=8)" 
      Index Cond: (latitude IS NOT NULL)" 
      Filter: (area2 = 18)" 

요청시

... (가) 출력을 분석 설명 여기에 에드

1)

Result (cost=6.07..6.08 rows=1 width=0) (actual time=10.992..10.993 rows=1 loops=1)" 
InitPlan 1 (returns $0)" 
    -> Limit (cost=0.00..6.07 rows=1 width=8) (actual time=10.985..10.986 rows=1 loops=1)" 
      -> Index Scan using longitude on reports (cost=0.00..139617.49 rows=22983 width=8) (actual time=10.983..10.983 rows=1 loops=1)" 
       Index Cond: (longitude IS NOT NULL)" 
       Filter: (area2 = 18)" 
Total runtime: 11.033 ms" 

2)

Result (cost=5.95..5.96 rows=1 width=0) (actual time=259.749..259.749 rows=1 loops=1)" 
InitPlan 1 (returns $0)" 
    -> Limit (cost=0.00..5.95 rows=1 width=8) (actual time=259.740..259.740 rows=1 loops=1)" 
      -> Index Scan using latitude on reports (cost=0.00..136754.07 rows=22983 width=8) (actual time=259.739..259.739 rows=1 loops=1)" 
       Index Cond: (latitude IS NOT NULL)" 
       Filter: (area2 = 18)" 
Total runtime: 259.789 ms" 
--------------------- 

무슨 일입니까? 두 번째 쿼리를 올바르게 실행하고 빠르게 실행할 수있는 방법은 무엇입니까? 두 설정 모두 내가 말할 수있는 한 동일합니다.

+0

이전에 '진공관 전체 분석'을 수행 했습니까? 당신은'EXPLAIN ANALYZE' 또는 단지'EXPLAIN'을 했습니까? – ckruse

+0

복합 색인이 관련되어 있습니까?우리에게 테이블 정의를 보여 주시고,'explain analyze'의 결과를 출력하십시오 – wildplasser

+1

정말 정확한 테이블과 인덱스 정의를 이와 같은 질문에 포함시켜야합니다. 어떤 열이'NOT NULL'입니까? 색인 크기? 'VACUUM FULL ANALYZE'가 아무 것도 변경합니까? 'CLUSTER가 USING USING idx1'을보고하고 'CLUSTER가 USING USING idx2를보고합니다'라는 보고서가 변경됩니까? (나는 그것을 기대할 것이다!) –

답변

3

첫째, 인덱스가 쿼리 속도를 보장하지 않습니다. 둘째, 성능 고려 사항을 수행 할 때 각 쿼리를 여러 번 실행해야합니다. 쿼리를 길이에 영향을 줄 수있는 인덱스를로드하고 캐시에로드하는 오버 헤드가 있습니다.

저는 Postgres의 전문가는 아니지만, 이것에 대해 생각할 때 저는 그렇게 놀랍지가 않습니다.

쿼리 계획은 인덱스를 반복하면서 area2 = 18과 일치하는 해당 행을 찾은 다음 첫 번째 행에서 중지합니다 (인덱스를 사용하므로 가장 낮은 값에서 시작하여 위쪽으로 이동할 수 있음) . 이것은 어떻게 작동하는지에 대한 추측입니다. 나는 Postgres가 정확히 이것을하고 있는지 모른다.

어쨌든이 지역은 위도 색인의 시작보다 경도 색인의 시작에 훨씬 가깝습니다. 그래서 첫 번째 일치하는 레코드를 찾습니다. 이 설명이 정확하다면, 그 지역은 상대적으로 서쪽 (경도가 낮다)과 상대적으로 북쪽 (위도가 더 높음)으로 데이터베이스의 다른 것들과 비교할 때 좋습니다.

그런데 많은 영역이 있다고 가정하면 Area2에 대한 색인으로 더 나은 결과를 얻을 수 있습니다.

+0

입력에 대한 감사 - 거기에 실제로 또한 area2에 대한 색인입니다 - 그냥 포스트 그레스 그것을 사용하지 않는 것으로 보인다 ... – user1051849

2

색인 스캔을 받고 있지만 검사 된 레코드의 수는 area2 조건과 일치하도록 이동해야하는 목록의 최대 거리에 따라 다릅니다.

area2 분포가 이상하지 않은 한이 쿼리를 최적화하려면 (area2, latitude)(area2, longitude)에 복합 인덱스를 넣어야합니다. 나는 당신이 < 10ms를 얻을 것이라고 생각합니다. PG는 비트 맵 힙 스캔 기능을 사용하여 area2에 별도의 인덱스를 합성 인덱스 대신 기존 인덱스와 결합 할 수도 있습니다.