여러 열 인덱스 및 성능


31

다중 열 인덱스가있는 테이블이 있으며 쿼리에서 최대 성능을 얻기 위해 인덱스를 올바르게 정렬하는 것에 대해 의문이 있습니다.

시나리오 :

  • 약 백만 개의 행이있는 PostgreSQL 8.4

  • c1 열의 값 은 약 100 개의 서로 다른 값을 가질 수 있습니다 . 값이 고르게 분포되어 있다고 가정 할 수 있으므로 가능한 모든 값에 대해 약 10000 개의 행이 있습니다.

  • c2 열 은 1000 개의 다른 값을 가질 수 있습니다 . 가능한 모든 값에 대해 1000 개의 행이 있습니다.

데이터를 검색 할 때 조건에는 항상이 두 열의 값이 포함되므로 테이블에는 c1과 c2를 결합하는 다중 열 인덱스가 있습니다. 필터링을 위해 단 하나의 열을 사용하는 쿼리가있는 경우 다중 인덱스에서 을 올바르게 정렬 하는 것이 중요하다는 것을 읽었습니다 . 이 시나리오에서는 그렇지 않습니다.

내 질문은 이것입니다.

필터 중 하나가 훨씬 더 작은 데이터 세트를 선택한다는 사실을 고려할 때 첫 번째 인덱스가 가장 선택적인 인덱스 (더 작은 세트를 허용하는 인덱스) 인 경우 성능을 향상시킬 수 있습니까? 참조 기사에서 그래픽을 볼 때 까지이 질문을 고려하지 않았습니다.

여기에 이미지 설명을 입력하십시오

여러 열 인덱스 에 대한 참조 기사에서 가져온 이미지 .

쿼리는 필터링을 위해 두 열의 값을 사용합니다. 필터링을 위해 단 하나의 열을 사용하는 쿼리가 없습니다. 그들 모두는 : WHERE c1=@ParameterA AND c2=@ParameterB. 다음과 같은 조건이 있습니다.WHERE c1 = "abc" AND c2 LIKE "ab%"

답변:


36

대답

웹 사이트를 참조하므로 다음 use-the-index-luke.com장을 고려하십시오.

인덱스 사용, 루크 (Luke)›어디에서 절›범위 검색› 더 크고 작으며

@ypercube의 조언 이 정확하고 요약하는 이유를 설명합니다 (두 열 인덱스, 하나는 평등 테스트, 다른 하나는 범위에 대한 테스트 ) .

Rule of thumb: index for equality first  then for ranges.

하나의 열에도 적합합니까?

하나의 열에 대한 쿼리에 대해 수행 할 작업 이 분명한 것 같습니다. 이 관련 질문에 대한 자세한 내용과 벤치 마크 :

덜 선택적인 열?

그 외에도 두 열에 대해 동등 조건 만 있으면 어떻게 됩니까?

중요하지 않습니다 . 자체적으로 조건을 수신 할 가능성이 높은 컬럼을 먼저 놓으십시오. 실제로는 중요합니다.

이 데모를 고려하거나 직접 재현하십시오. 100k 행이있는 두 열의 간단한 테이블을 만듭니다. 하나는 매우 적고 다른 하나는 많은 고유 값을 갖습니다.

CREATE TEMP TABLE t AS
SELECT (random() * 10000)::int AS lots
     , (random() * 4)::int     AS few
FROM generate_series (1, 100000);

DELETE FROM t WHERE random() > 0.9;  -- create some dead tuples, more "real-life"

ANALYZE t;

SELECT count(distinct lots)   -- 9999
     , count(distinct few)    --    5
FROM   t;

질문:

SELECT *
FROM   t
WHERE  lots = 2345
AND    few = 2;

EXPLAIN ANALYZE 출력 (캐싱 효과를 제외하려면 10 개 중 최고) :

t에서 연속 스캔 (비용 = 0.00..5840.84 행 = 2 폭 = 8)
               (실제 시간 = 5.646..15.535 행 = 2 루프 = 1)
  필터 : ((lots = 2345) AND (few = 2))
  버퍼 : 로컬 적중 = 443
총 런타임 : 15.557ms

색인을 추가하고 다시 테스트하십시오.

CREATE INDEX t_lf_idx ON t(lots, few);
t에서 t_lf_idx를 사용한 인덱스 스캔 (비용 = 0.00..3.76 행 = 2 너비 = 8)
                                (실제 시간 = 0.008..0.011 행 = 2 루프 = 1)
  인덱스 조건 : ((lots = 2345) AND (few = 2))
  버퍼 : 로컬 적중 = 4
총 런타임 : 0.027ms

다른 색인을 추가하고 다시 테스트하십시오.

DROP INDEX t_lf_idx;
CREATE INDEX t_fl_idx  ON t(few, lots);
t에서 t_fl_idx를 사용한 인덱스 스캔 (비용 = 0.00..3.74 행 = 2 폭 = 8)
                                (실제 시간 = 0.007..0.011 행 = 2 루프 = 1)
  인덱스 조건 : ((몇 = 2) AND (lots = 2345))
  버퍼 : 로컬 적중 = 4
총 런타임 : 0.027ms

인덱스의 3 개 이상의 열에 대해서도 마찬가지입니까?
건초

@hayd : "this"가 무엇을 의미하는지 잘 모르겠습니다. 당신은 새로운 질문을 할 수 있습니다 . 컨텍스트를 위해 항상이 것을 참조 할 수 있습니다. (그리고 의견을 다시 보내려면 링크를
남겨주세요

"이것"은 "인덱스 정의에 3 개 이상의 열이있는 경우 인덱스 정의의
순서가 결정됨

@hayd : 가장 중요한 점 : btree 인덱스는 선행 인덱스 표현식 에서 동등한 조건을 가진 쿼리에 적합합니다 . 그 중 순서는 대부분 관련이 없습니다. 코멘트에 맞지 않는 다른 많은 세부 사항 ...
Erwin Brandstetter

고마워, 나는 일관된 질문을 작성하고 그것에 연결하려고합니다.
건초

11

예를 들어,이 2 개의 열과 관련된 쿼리가 모두 두 열의 동등 검사이면 다음과 같습니다.

WHERE c1=@ParameterA AND c2=@ParameterB

이것을 귀찮게하지 마십시오. 나는 어떤 차이가 있을지 의심하고, 차이가 있다면 무시할 수있을 것이다. 데이터와 서버 설정을 사용하여 언제든지 테스트 할 수 있습니다. DBMS의 다른 버전은 최적화와 관련하여 약간 다르게 작동 할 수 있습니다.

인덱스 내부의 순서는 하나의 열만 검사하거나 불평등 조건 또는 한 열의 조건과 다른 열의 그룹화 등 다른 유형의 쿼리에 중요합니다.

두 주문 중 하나를 선택하려면 선택적인 열을 먼저 선택합니다. 열이있는 테이블 고려 yearmonth. WHERE year = 2000조건 또는 a WHERE year BETWEEN 2000 AND 2013또는 a 가 필요할 가능성이 높습니다 WHERE (year, month) BETWEEN (1999, 6) AND (2000, 5).

이 유형의 쿼리 WHERE month = 7 GROUP BY year는 확실하게 원할 수도 있지만 (7 월에 태어난 사람 찾기) 덜 자주 수행됩니다. 물론 테이블에 저장된 실제 데이터에 따라 다릅니다. 지금 주문을 하나 선택 (c1, c2)하고 나중에 다른 색인을 언제든지 추가 할 수 있습니다 (c2, c1).


OP의 의견 다음에 업데이트 :

다음과 같은 조건이 있습니다. WHERE c1 = 'abc' AND c2 LIKE 'ab%'

이 유형의 쿼리는 정확히 c2열의 범위 조건 이며 (c1, c2)인덱스 가 필요합니다 . 리버스 유형의 쿼리도있는 경우 :

WHERE c2 = 'abc' AND c1 LIKE 'ab%'

(c2, c1)인덱스 가 있으면 좋을 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.