| 포스트그레SQL 8.3.23 문서 | ||||
|---|---|---|---|---|
| 이전 | 빠르게 뒤로 | 55장. 플래너가 통계를 사용하는 방법 | Fast Forward | 다음 | 
아래에 표시된 예는 다음의 테이블을 사용합니다.PostgreSQL회귀 테스트 데이터베이스. 는 표시된 출력은 버전 8.3에서 가져온 것입니다. 이전의 행동 (또는 그 이후) 버전은 다를 수 있습니다. 이후에도 참고하세요.분석생성하는 동안 무작위 샘플링을 사용합니다. 통계에 따르면 새로운 결과가 나오면 결과가 약간 변경됩니다.분석.
아주 간단한 쿼리부터 시작하겠습니다.
설명 토토 * FROM tenk1;
                         쿼리 계획
------------------------------------------------
 tenk1의 시퀀스 스캔(비용=0.00..458.00행=10000너비=244)
  계획자가 카디널리티를 결정하는 방법tenk1다음으로 덮여있습니다섹션 14.2, 그러나 여기서는 다음에 대해 반복됩니다. 완전성. 페이지 및 행 수는 다음에서 조회됩니다.pg_class:
pg_class WHERE relname = 'tenk1'에서 relpages, reltuples 선택;
 렐페이지 | 리트플스
---------+------------
      358 |     10000
  이 숫자는 지난번 현재의 숫자입니다.진공또는분석에 테이블. 그런 다음 플래너는 실제 현재 수를 가져옵니다. 테이블의 페이지(이것은 비용이 적게 드는 작업이므로 테이블 스캔). 만약 그것이 다르다면relpages그런 다음reltuples에 따라 크기가 조정되어 현재 예상 행 수입니다. 이 경우 값은 다음과 같습니다. 정확하므로 행 추정치는 다음과 같습니다.reltuples.
범위 조건이 포함된 예로 넘어가겠습니다어디절:
설명 선택 * FROM tenk1 WHERE 고유1 < 1000;
                                   쿼리 계획
--------------------------------------------------------------------------------
 tenk1의 비트맵 힙 스캔(비용=24.06..394.64행=1007 너비=244)
   조건 재확인: (unique1 < 1000)
   - tenk1_unique1의 비트맵 인덱스 스캔(비용=0.00..23.80 행=1007 너비=0)
         인덱스 조건: (unique1 < 1000)
  계획자가 다음을 조사합니다.어디절
  조건을 지정하고 연산자에 대한 토토성 함수를 찾습니다.<에pg_operator. 칼럼에 담겨있습니다.오프레스트및 이 경우 항목
  이다scalarltsel.scalarltsel함수는 히스토그램을 검색합니다.
  에 대한고유1frompg_statistics. 수동 쿼리의 경우 더 많은 것입니다.
  더 간단하게 보는 것이 편리합니다pg_stats보기:
pg_stats에서 히스토그램_바운드 선택
WHERE 테이블 이름='tenk1' AND attname='unique1';
                   히스토그램_바운드
----------------------------
 0,993,1997,3050,4040,5036,5957,7057,8029,9016,9995
  다음으로 차지하는 히스토그램의 비율"< 1000"해결되었습니다. 이것은 토토성. 히스토그램은 범위를 동일한 빈도로 나눕니다. 버킷이 있으므로 우리가 해야 할 일은 우리의 가치가 있는 버킷을 찾는 것뿐입니다. 포함되어 있으며 계산 중입니다부분의 그것과모두그들 중 전에. 값 1000은 분명히 두 번째 버킷에 있습니다. (993-1997). 각 내부 값의 선형 분포를 가정합니다. 버킷의 선택성을 다음과 같이 계산할 수 있습니다.
토토성 = (1 + (1000 - 버킷[2].min)/(버킷[2].max - 버킷[2].min))/num_buckets
            = (1 + (1000 - 993)/(1997 - 993))/10
            = 0.100697
  즉, 하나의 전체 버킷에 선형 분수를 더한 것입니다. 둘째, 버킷 수로 나눕니다. 예상 수 이제 행은 토토성과 카디널리티tenk1:
행 = rel_cardinality * 토토성
     = 10000 * 0.100697
     = 1007(반올림)
  다음으로 동등 조건이 있는 예를 고려해 보겠습니다. 그어디에서절:
EXPLAIN SELECT * FROM tenk1 WHERE stringu1 = 'CRAAAA';
                        쿼리 계획
--------------------------------
 tenk1의 시퀀스 스캔(비용=0.00..483.00행=30너비=244)
   필터: (stringu1 = 'CRAAAA'::name)
  다시 기획자는 다음을 조사합니다.어디절 조건을 지정하고 다음에 대한 선택 함수를 찾습니다.=, 즉eqsel. 평등 추정의 경우 히스토그램은 다음과 같습니다.
  유용하지 않음; 대신에가장 일반적
  값 (MCVs)는 다음과 같은 용도로 사용됩니다.
  선택성을 결정합니다. MCV를 살펴보겠습니다.
  나중에 유용할 몇 가지 추가 열:
pg_stats에서 null_frac, n_distinct, Most_common_vals, Most_common_freqs 선택 WHERE 테이블 이름='tenk1' AND attname='stringu1'; 널_분수 | 0 n_distinct | 676 가장_공통_값 | EJAAAA,BBAAAA,CRAAAA,FCAAAA,FEAAAA,GSAAAA,JOAAAA,MCAAAA,NAAAAA,WGAAAA
이후CRAAAA다음 목록에 나타납니다. MCV의 선택성은 단지 해당 항목에 불과합니다. 가장 일반적인 주파수 목록(MCFs):
토토성 = mcf[3]
            = 0.003
  이전과 마찬가지로 예상 행 수는 다음의 곱입니다. 이것은 카디널리티와 함께텐크1:
행 = 10000 * 0.003
     = 30
  이제 동일한 쿼리를 고려하지만 다음과 같지 않은 상수를 사용합니다. 에서MCV목록:
설명 선택 * FROM tenk1 WHERE stringu1 = 'xxx';
                        쿼리 계획
--------------------------------
 tenk1의 시퀀스 스캔(비용=0.00..483.00행=15너비=244)
   필터: (stringu1 = 'xxx'::name)
  이것은 완전히 다른 문제입니다. 어떻게 추정할 것인가? 값이 다음과 같을 때의 선택성아님에서MCV목록. 접근 방식은 사실을 이용하는 것입니다. 그 값이 목록에 없다는 사실과 모든 것에 대한 빈도MCVs:
토토성 = (1 - 합계(mvf))/(num_distinct - num_mcv)
            = (1 - (0.00333333 + 0.003 + 0.003 + 0.003 + 0.003 + 0.003 +
                    0.003 + 0.003 + 0.003 + 0.003))/(676 - 10)
            = 0.0014559
  즉, 다음에 대한 모든 주파수를 합산하십시오.MCVs를 하나에서 뺀 다음 나눕니다. 수에 따라기타고유한 값. 이는 다음의 비율을 가정하는 것과 같습니다. MCV가 아닌 열은 균등하게 분포됩니다. 다른 모든 고유한 값 중에서 없음을 참고하세요. null 값이므로 이에 대해 걱정할 필요가 없습니다(그렇지 않으면 분자에서 널 분수도 뺍니다. 는 예상 행 수는 평소와 같이 계산됩니다.
행 = 10000 * 0.0014559
     = 15(반올림)
  이전 예는고유1 <
  1000너무 단순화한 내용이었습니다scalarltsel정말 그렇습니다; 이제 우리는 보았다
  MCV 사용의 예를 통해 좀 더 자세히 설명할 수 있습니다.
  그 예는 지금까지는 정확했습니다. 왜냐하면고유1아무것도 없는 고유한 열입니다.
  MCV(분명히 다른 가치보다 더 일반적인 가치는 없습니다.
  값). 고유하지 않은 열의 경우 일반적으로
  히스토그램과 MCV 목록, 그리고히스토그램에 해당 부분이 포함되지 않습니다.
  MCV로 표시되는 열 모집단. 우리는
  이렇게 하면 더 정확한 추정이 가능하기 때문입니다. 에서
  이 상황scalarltsel직접
  조건을 적용합니다(예:"<
  1000")를 MCV 목록의 각 값에 추가하고
  조건이 참인 MCV의 주파수입니다. 이
  부분 내에서 선택성의 정확한 추정치를 제공합니다.
  MCV 테이블입니다. 히스토그램은 같은 용도로 사용됩니다.
  위와 같은 방법으로 부분의 선택성을 추정합니다.
  MCV가 아닌 테이블을 찾은 다음 두 숫자를 결합하여
  전체 선택성을 추정합니다. 예를 들어 다음을 고려하세요.
EXPLAIN SELECT * FROM tenk1 WHERE stringu1 < 'IAAAAA';
                         쿼리 계획
----------------------------------
 tenk1의 시퀀스 스캔(비용=0.00..483.00행=3077너비=244)
   필터: (stringu1 < 'IAAAAA'::name)
  우리는 이미 다음에 대한 MCV 정보를 확인했습니다.stringu1, 히스토그램은 다음과 같습니다.
pg_stats에서 히스토그램_바운드 선택
WHERE 테이블 이름='tenk1' AND attname='stringu1';
                                히스토그램_바운드
--------------------------------------------------------------------------------
 AAAAAA,CQAAAA,FRAAAA,IBAAAA,KRAAAA,NFAAAA,PSAAAA,SGAAAA,VAAAAA,XLAAAA,ZZAAAA
  MCV 목록을 확인해보니 조건이 있는 것으로 나타났습니다.stringu1 < 'IAAAAA'첫 번째에 만족합니다. 마지막 4개가 아닌 6개 항목이므로 인구의 MCV 부분은
토토성 = 합계(관련 mvfs)
            = 0.00333333 + 0.003 + 0.003 + 0.003 + 0.003 + 0.003
            = 0.01833333
  모든 MCF를 합산하면 MCV로 표시되는 인구는 0.03033333이므로 히스토그램으로 표시되는 분수는 0.96966667입니다(다시 말하지만, null이 없으면 여기에서 제외해야 합니다.) 우리는 할 수 있다 값을 확인하세요.IAAAAA거의 떨어지다 세 번째 히스토그램 버킷 끝에 있습니다. 오히려 일부를 사용하여 다양한 캐릭터의 빈도에 대한 저속한 가정, 플래너는 해당 부분에 대해 추정치 0.298387에 도달했습니다. 다음보다 작은 히스토그램 모집단IAAAAA. 그런 다음 MCV에 대한 추정치를 결합합니다. 및 비MCV 모집단:
토토성 = mcv_selectivity + histogram_selectivity * histogram_fraction
            = 0.01833333 + 0.298387 * 0.96966667
            = 0.307669
행 = 10000 * 0.307669
            = 3077(반올림)
  이 특정 예에서는 MCV 목록의 수정 사항이 열 분포가 실제로 다음과 같기 때문에 상당히 작습니다. 매우 평평합니다(이러한 특정 값을 다음과 같이 보여주는 통계는 다른 것보다 더 흔한 것은 대부분 샘플링 오류 때문입니다). 일부 값이 훨씬 더 큰 보다 일반적인 경우 다른 것보다 일반적이지만 이 복잡한 프로세스는 유용한 정보를 제공합니다. 선택성이 가장 높기 때문에 정확성이 향상됩니다. 공통값이 정확하게 발견됩니다.
이제 하나 이상의 조건이 있는 경우를 고려해 보겠습니다.어디절:
설명 선택 * FROM tenk1 WHERE Unique1 < 1000 AND stringu1 = 'xxx';
                                   쿼리 계획
--------------------------------------------------------------------------------
 tenk1의 비트맵 힙 스캔(비용=23.80..396.91행=1너비=244)
   조건 재확인: (unique1 < 1000)
   필터: (stringu1 = 'xxx'::name)
   - tenk1_unique1의 비트맵 인덱스 스캔(비용=0.00..23.80 행=1007 너비=0)
         인덱스 조건: (unique1 < 1000)
  계획자는 두 조건이 독립적이라고 가정합니다. 조항의 개별 토토성이 함께 곱하면:
선택성 = 선택성(unique1 < 1000) * 선택성(stringu1 = 'xxx')
            = 0.100697 * 0.0014559
            = 0.0001466
행 = 10000 * 0.0001466
            = 1(반올림)
  다음에서 반환될 것으로 예상되는 행 수를 확인하세요. 비트맵 인덱스 스캔은 색인; 이는 비용 추정에 영향을 미치기 때문에 중요합니다. 후속 힙을 가져옵니다.
마지막으로 조인과 관련된 쿼리를 검토하겠습니다.
설명 선택 * tenk1 t1, tenk2 t2에서
t1.unique1 < 50 AND t1.unique2 = t2.unique2;
                                      쿼리 계획
-------------------------------------------------------------------------
 중첩 루프(비용=4.64..456.23행=50너비=488)
   - tenk1 t1의 비트맵 힙 스캔(비용=4.64..142.17 행=50 너비=244)
         조건 재확인: (unique1 < 50)
         - tenk1_unique1의 비트맵 인덱스 스캔(비용=0.00..4.63행=50너비=0)
               지수 조건: (고유1 < 50)
   - tenk2 t2에서 tenk2_unique2를 사용한 인덱스 스캔(비용=0.00..6.27행=1너비=244)
         인덱스 조건: (t2.unique2 = t1.unique2)
  제한사항tenk1, 고유1 < 50, 이전에 평가됩니다. 중첩 루프 조인. 이는 이전과 유사하게 처리됩니다. 범위 예. 이번에는 값 50이 첫 번째 버킷에 속합니다. 의고유1히스토그램:
토토성 = (0 + (50 - 버킷[1].min)/(버킷[1].max - 버킷[1].min))/num_buckets
            = (0 + (50 - 0)/(993 - 0))/10
            = 0.005035
행 = 10000 * 0.005035
            = 50(반올림)
  조인 제한은 다음과 같습니다.t2.unique2
  = t1.unique2. 교환원은 우리에게 친숙한 사람입니다.=, 그러나 선택성 함수가 얻어집니다.
  에서oprjoin열pg_operator그리고 입니다eqjoinsel. eqjoinsel통계정보를 조회합니다
  둘 다에 대해tenk2그리고tenk1:
pg_stats에서 테이블 이름, null_frac,n_distinct, Most_common_vals 선택
WHERE 테이블 이름 IN ('tenk1', 'tenk2') AND attname='unique2';
테이블 이름 | 널_분수 | n_distinct | 가장_공통_발
---------+------------+------------+----
 텐크1 |         0 |         -1 |
 텐크2 |         0 |         -1 |
  이 경우에는 없습니다MCV정보고유2모든 값이 다음과 같이 나타나기 때문입니다. 고유하므로 우리는 숫자에만 의존하는 알고리즘을 사용합니다. 두 관계에 대한 고유한 값과 해당 null 분수:
토토성 = (1 - null_frac1) * (1 - null_frac2) * min(1/num_distinct1, 1/num_distinct2)
            = (1 - 0) * (1 - 0) / 최대(10000, 10000)
            = 0.0001
  이것은 각 항목에 대해 하나에서 null 분수를 빼는 것입니다. 관계를 구별하고 최대 개수로 나눕니다. 가치. 조인이 방출할 가능성이 있는 행 수는 다음과 같습니다. 두 개의 데카르트 곱의 카디널리티로 계산됩니다. 입력에 선택성을 곱한 값:
행 = (outer_cardinality * inner_cardinality) * 토토성
     = (50 * 10000) * 0.0001
     = 50
  두 열에 대한 MCV 목록이 있었다면,eqjoinsel직접 비교를 사용했을 것입니다.
  부품 내 조인 선택성을 결정하기 위한 MCV 목록
  MCV로 표시되는 열 모집단의 수입니다. 견적
  나머지 인구는 동일한 접근 방식을 따릅니다.
  여기에 표시됩니다.
우리가 보여준 것을 주목하세요inner_cardinality10000으로 즉, 수정되지 않은 크기tenk2. 어쩌면 검사에서 나타납니다.설명조인 행의 추정값이 50 * 1에서 나온다고 출력합니다. 즉, 외부 행 수에 예상 행 수를 곱한 값 각 내부 인덱스 스캔으로 얻은 것입니다.tenk2. 하지만 그렇지 않습니다. 조인 특정 조인 계획이 실행되기 전에 관계 크기가 추정됩니다. 고려되었습니다. 모든 것이 잘 작동한다면 두 가지 방법이 있습니다. 조인 크기를 추정하면 거의 동일한 답이 생성됩니다. 그러나 반올림 오류 및 기타 요인으로 인해 때때로 상당히 차이가 납니다.
더 자세한 내용에 관심이 있는 분들을 위해 테이블 크기(모든 것 이전에)어디절)이 완료되었습니다.src/backend/optimizer/util/plancat.c. 일반 조항 선택성에 대한 논리는 다음과 같습니다.src/backend/optimizer/path/clausesel.c. 는 연산자별 선택 함수는 주로 다음에서 찾을 수 있습니다.src/backend/utils/adt/selfuncs.c.