2025년 9월 25일:토토 커뮤니티 : 토토
이 문서는 지원되지 않는 PostgreSQL 버전에 대한 것입니다.
당신은 다음과 같은 페이지를 보고 싶을 수도 있습니다.토토 캔 : 문서 : 17 : 68 장. 플래너가 통계를 사용하는 방법버전 또는 위에 나열된 다른 지원 버전 중 하나를 사용하세요.

52장. 플래너의 토토 베이 방법 통계

이 장은 다음에서 다룬 내용을 바탕으로 작성되었습니다.섹션 13.1그리고토토 핫, 그리고 어떻게 플래너는 시스템 통계를 사용하여 행 수를 추정합니다. 쿼리의 각 단계가 반환될 수 있습니다. 이는 중요한 부분입니다. 계획/최적화 프로세스를 통해 많은 원시 정보 제공 비용 계산을 위한 자료입니다.

이 장의 목적은 코드를 문서화하는 것이 아닙니다 — 코드 자체에서 수행하는 것이 더 좋지만 방법에 대한 개요를 제시합니다. 작동합니다. 이것은 아마도 누군가의 학습 곡선을 완화할 것입니다. 나중에 코드를 읽고 싶은 사람. 그 결과, 선택한 접근 방식은 일련의 점진적인 분석을 더 많이 분석하는 것입니다. 복잡한 예.

아래에 표시된 출력 및 알고리즘은 버전에서 가져왔습니다. 8.0. 이전(또는 이후) 버전의 동작은 다를 수 있습니다.

52.1. 행 추정 예

회귀 테스트 데이터베이스에서 가져온 예를 토토 베이하여, 아주 간단한 쿼리부터 시작해 보겠습니다.

설명 선택 * FROM tenk1;

                         쿼리 계획
------------------------------------------------
 tenk1의 시퀀스 스캔(비용=0.00..445.00행=10000너비=244)

계획자가 카디널리티를 결정하는 방법tenk1다음으로 덮여있습니다섹션 13.1, 하지만 완전성을 위해 여기에서 반복합니다. 행 수를 조회합니다. 에서pg_class:

pg_class WHERE relname = 'tenk1'에서 reltuples, relpages 선택;

 렐페이지 | 리트플스
---------+------------
      345 |     10000

플래너가 다음을 확인합니다relpages추정(이것은 저렴합니다. 작동) 잘못된 경우 크기가 조정될 수 있습니다.reltuples행 추정값을 얻으려면. 이에 그렇지 않은 경우에는 다음과 같습니다.

행 = 10000

범위 조건이 포함된 예로 넘어가겠습니다어디절:

설명 선택 * FROM tenk1 WHERE 고유1 < 1000;

                         쿼리 계획
----------------------------------
 tenk1의 시퀀스 스캔(비용=0.00..470.00행=1031너비=244)
   필터: (고유1 < 1000)

기획자가 다음을 조사합니다.어디절 조건:

고유1 < 1000

그리고 연산자에 대한 제한 함수를 찾습니다<pg_operator. 칼럼에 담겨있습니다.오프레스트, 결과는 다음과 같습니다. 경우는scalarltsel.scalarltsel함수 검색 히스토그램고유1frompg_statistics- 우리는 따라갈 수 있어요 더 간단한 방법을 토토 베이하여 이 작업을 수행합니다.pg_stats보기:

pg_stats에서 히스토그램_바운드 선택 
WHERE 테이블 이름='tenk1' AND attname='unique1';

                   히스토그램_바운드
----------------------------
 1,970,1943,2958,3971,5069,6028,7007,7919,8982,9995

다음으로 차지하는 히스토그램의 비율"< 1000"해결되었습니다. 이것은 선택성. 히스토그램은 범위를 동일하게 나눕니다. 빈도 버킷이 있으므로 우리가 해야 할 일은 버킷을 찾는 것뿐입니다. 우리의 가치는 중요합니다부분그리고전체이전의 것들 중. 가치 1000은 분명히 두 번째(970 - 1943) 버킷에 있으므로 각 버킷 내 값의 선형 분포를 가정하면 선택성을 다음과 같이 계산할 수 있습니다.

선택성 = (1 + (1000 - bckt[2].min)/(bckt[2].max - bckt[2].min))/num_bckts
            = (1 + (1000 - 970)/(1943 - 970))/10
            = 0.1031

즉, 하나의 전체 버킷에 선형 분수를 더한 것입니다. 둘째, 버킷 수로 나눕니다. 추정 수 이제 선택도의 곱으로 행을 계산할 수 있습니다. 및 카디널리티텐크1:

행 = rel_cardinality * 선택성
     = 10000 * 0.1031
     = 1031

다음으로 동등 조건이 있는 예를 고려해 보겠습니다. 그어디절:

EXPLAIN SELECT * FROM tenk1 WHERE stringu1 = 'ATAAAA';

                        쿼리 계획
--------------------------------
 tenk1의 시퀀스 스캔(비용=0.00..470.00행=31너비=244)
   필터: (stringu1 = 'ATAAAA'::이름)

다시 기획자는 다음을 조사합니다.어디에서절 조건:

stringu1 = 'ATAAAA'

그리고 다음에 대한 제한 기능을 찾습니다=즉,eqsel. 이 경우는 가장 일반적인 값이므로 약간 다릅니다 —MCVs는 다음을 결정하는 데 사용됩니다. 선택성. 몇 가지 추가 사항을 포함하여 다음을 살펴보겠습니다. 나중에 유용할 열:

pg_stats에서 null_frac, n_distinct, Most_common_vals, Most_common_freqs 선택 
WHERE 테이블 이름='tenk1' AND attname='stringu1';

널_분수 | 0
n_distinct | 672
가장_공통_값 | FDAAAA,NHAAAA,ATAAAA,BGAAAA,EBAAAA,MOAAAA,NDAAAA,OWAAAA,BHAAAA,BJAAAA

선택성은 단지 가장 일반적인 주파수일 뿐입니다 (MCF)에 해당 세 번째MCV— 'ATAAAA':

선택성 = mcf[3]
            = 0.003

예상 행 수는 이것의 곱입니다. 카디널리티 포함텐크1다음과 같이 이전:

행 = 10000 * 0.003
     = 30

표시된 숫자설명이다 일부 사후 추정 확인으로 인해 이보다 하나 더 있습니다.

이제 동일한 쿼리를 고려하지만 다음과 같지 않은 상수를 사용합니다. 에서MCV목록:

EXPLAIN SELECT * FROM tenk1 WHERE stringu1 = 'xxx';

                        쿼리 계획
--------------------------------
 tenk1의 시퀀스 스캔(비용=0.00..470.00행=15너비=244)
   필터: (stringu1 = 'xxx'::name)

이것은 상당히 다른 문제입니다. 어떻게 추정할 것인가? 값이 다음과 같을 때의 선택성아님에서MCV목록. 접근 방식은 사실을 이용하는 것입니다. 해당 값이 목록에 없으며 지식과 결합되어 있음 모든 것에 대한 주파수 중MCVs:

선택성 = (1 - 합계(mvf))/(num_distinct - num_mcv)
            = (1 - (0.00333333 + 0.00333333 + 0.003 + 0.003 + 0.003 
            + 0.003 + 0.003 + 0.003 + 0.00266667 + 0.00266667))/(672 - 10)
            = 0.001465

즉, 다음에 대한 모든 주파수를 합산하십시오.MCVs를 하나에서 빼세요 — 왜냐하면 그것은아님다음 중 하나 이것을 다음과 같이 나눕니다.나머지고유한 값. 공지사항 null 값이 없으므로 걱정할 필요가 없습니다. 그. 예상 행 수는 평소와 같이 계산됩니다.

행 = 10000 * 0.001465
     = 15

더 많은 사례를 고려하기 위해 복잡성을 증가시키자 에서 하나 이상의 조건어디절:

설명 선택 * FROM tenk1 WHERE Unique1 < 1000 AND stringu1 = 'xxx';

                       쿼리 계획
----------------------------------------------
 tenk1의 시퀀스 스캔(비용=0.00..495.00행=2너비=244)
   필터: ((unique1 < 1000) AND (stringu1 = 'xxx'::name))

독립성을 가정하고 선택성을 높였습니다. 개별 제한 사항이 함께 곱해집니다.

선택성 = 선택성(unique1 < 1000) * 선택성(stringu1 = 'xxx')
            = 0.1031 * 0.001465
            = 0.00015104

행 추정값은 이전과 같이 계산됩니다:

행 = 10000 * 0.00015104
     = 2

마지막으로 다음을 포함하는 쿼리를 조사하겠습니다.가입함께어디절:

설명 선택 * tenk1 t1, tenk2 t2에서 
t1.unique1 < 50 AND t1.unique2 = t2.unique2;

                                      쿼리 계획
---------------------------------------------------------------
 중첩 루프(비용=0.00..346.90행=51너비=488)
   - tenk1 t1에서 tenk1_unique1을 사용한 인덱스 스캔(비용=0.00..192.57 행=51 너비=244)
         지수 조건: (고유1 < 50)
   - tenk2 t2에서 tenk2_unique2를 사용한 인덱스 스캔(비용=0.00..3.01 행=1 너비=244)
         인덱스 조건: ("outer".unique2 = t2.unique2)

제한사항tenk1 "고유1 < 50"평가됨 중첩 루프 조인 전에. 이는 다음과 유사하게 처리됩니다. 이전 범위의 예. 에 대한 제한 연산자<isscalarlteqsel전과 같지만 이번에는 값 50은의 첫 번째 버킷에 있습니다.고유1히스토그램:

선택성 = (0 + (50 - bckt[1].min)/(bckt[1].max - bckt[1].min))/num_bckts
            = (0 + (50 - 1)/(970 - 1))/10
            = 0.005057

행 = 10000 * 0.005057
            = 51

조인 제한사항은 다음과 같습니다.

t2.unique2 = t1.unique2

이것은 조인 방법이 중첩 루프이기 때문입니다.tenk1외부 루프에 있습니다. 교환원은 우리에게 친숙한 사람입니다.=, 그러나 제한 기능은 다음에서 얻습니다.oprjoinpg_operator- 그리고는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) * 최소(1/10000, 1/1000)
            = 0.0001

이것은 각 항목에 대해 하나에서 null 분수를 빼는 것입니다. 관계를 구별하고 두 개의 별개의 최대값으로 나눕니다. 가치. 조인이 방출할 가능성이 있는 행 수는 다음과 같습니다. 두 개의 데카르트 곱의 카디널리티로 계산됩니다. 중첩 루프의 노드에 선택성을 곱합니다.

행 = (outer_cardinality * inner_cardinality) * 선택성
     = (51 * 10000) * 0.0001
     = 51

더 자세한 내용에 관심이 있는 분들을 위해 관계의 행 수는 다음과 같습니다.src/backend/optimizer/util/plancat.c. 는 조항 선택성에 대한 계산 논리는 다음과 같습니다.src/backend/optimizer/path/clausesel.c. 는 연산자의 실제 구현 및 조인 제한 함수는에서 찾을 수 있습니다.src/backend/utils/adt/selfuncs.c.