2025년 9월 25일:토토 커뮤니티 : 토토
이 문서는 지원되지 않는 롤 토토 버전에 대한 것입니다.
당신은 다음과 같은 페이지를 보고 싶을 수도 있습니다.PostgreSQL : 문서 : 17 : 68.1. 행 윈 토토 예버전 또는 위에 나열된 다른 지원 버전 중 하나를 사용하세요.

60.1. 행 롤 토토 예

아래에 표시된 예는 다음의 테이블을 사용합니다.롤 토토회귀 테스트 데이터베이스. 는 표시된 출력은 버전 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에 따라 크기가 조정되어 현재 예상 행 수입니다. 위의 예에서 값은relpages최신이므로 행 추정치는 다음과 같습니다.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)

계획자가 다음을 조사합니다.어디절 조건을 지정하고 연산자에 대한 선택성 함수를 찾습니다.<inpg_operator. 칼럼에 담겨있습니다.오프레스트, 이 경우 항목은scalarltsel.scalarltsel함수는 다음에 대한 히스토그램을 검색합니다.고유1에서pg_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

즉, 하나의 전체 버킷에 두 번째의 선형 분수를 더한 것입니다. 버킷 수로 나눕니다. 예상 행 수는 다음과 같습니다. 이제 선택성과 카디널리티텐크1:

행 = 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가 아닌 열은 모든 MCV에 균등하게 배포됩니다. 다른 고유한 값. null 값이 없으므로 주의하세요. 우리는 그것들에 대해 걱정할 필요가 없습니다(그렇지 않으면 우리는 분자의 null 분수도 마찬가지입니다). 예상 수 그런 다음 행은 평소와 같이 계산됩니다.

행 = 10000 * 0.0014559
     = 15(반올림)

이전 예는고유1 < 1000과도하게 단순화한 것입니다scalarltsel정말 그렇습니다; 이제 우리는 MCV 사용의 예를 통해 좀 더 자세히 설명할 수 있습니다. 는 예는 지금까지 정확했습니다. 왜냐하면고유1MCV가 없는 고유 열입니다. (분명히 어떤 값도 다른 값보다 더 일반적이지 않습니다.) 에 대한 고유하지 않은 열의 경우 일반적으로 히스토그램과 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'처음 6개에 만족합니다. 마지막 4개가 아닌 항목이므로 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)
         인덱스 조건: (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. 교환원은 우리에게 친숙한 사람입니다.=, 그러나 선택성 함수는 다음에서 얻습니다.oprjoinpg_operator그리고 입니다eqjoinsel. eqjoinsel통계정보를 조회합니다 둘 다에 대해텐크2그리고텐크1:

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.