히스토그램 외부의 카디널리티 추정


14

설정

카디널리티 예상을 이해하는 데 문제가 있습니다. 테스트 설정은 다음과 같습니다.

  • 2010 버전의 스택 오버플로 데이터베이스
  • SQL Server 2017 CU15 + GDR (KB4505225)-14.0.3192.2
  • 새로운 CE (호환성 수준 140)

이 proc이 있습니다.

USE StackOverflow2010;
GO

CREATE OR ALTER PROCEDURE #sp_PostsByCommentCount
    @CommentCount int
AS
BEGIN
    SELECT * 
    FROM dbo.Posts p
    WHERE 
        p.CommentCount = @CommentCount
    OPTION (RECOMPILE); 
END;
GO

dbo.Posts테이블 에 비 클러스터형 인덱스 또는 통계가 없습니다 (에 클러스터형 인덱스가 있음 Id).

이에 대한 예상 계획을 요청할 때 나오는 "추정 된 행" dbo.Posts은 1,934.99입니다.

EXEC #sp_PostsByCommentCount @CommentCount = 51;

예상 계획을 요청할 때 다음 통계 오브젝트가 자동으로 작성되었습니다.

DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);

SSMS의 통계 출력 스크린 샷

그 하이라이트는 다음과 같습니다.

  • 통계는 1.81 % (67,796 / 3,744,192)의 샘플링 속도가 매우 낮습니다.
  • 31 개의 히스토그램 단계 만 사용되었습니다
  • "모든 밀도"값은 0.03030303(33 개의 개별 값이 샘플링 됨)
  • RANGE_HI_KEY히스토그램 의 마지막 은 50 EQ_ROWS이며 1은

질문

50보다 큰 값 (최대 2,147,483,647 포함)을 전달하면 1,934.99 행 추정값이 생성됩니다. 이 추정치를 생성하기 위해 어떤 계산 또는 값이 사용됩니까? 그런데 레거시 카디널리티 추정기는 1 행의 추정치를 생성합니다.

내가 시도한 것

여기 내가 가진 몇 가지 이론, 내가 시도한 것들, 또는 이것에 대해 조사하면서 파헤칠 수있는 추가 정보가 있습니다.

밀도 벡터

나는 처음에 내가 사용했던 것처럼 밀도 벡터가 될 것이라고 생각했습니다 OPTION (OPTIMIZE FOR UNKNOWN). 그러나이 stats 객체의 밀도 벡터는 3,744,192 * 0.03030303 = 113,460이므로 그렇지 않습니다.

확장 이벤트

이벤트를 수집하는 확장 이벤트 세션 query_optimizer_estimate_cardinality(Paul White의 블로그 게시물 Cardinality Estimation : Combining Density Statistics )에서 실행을 시도 했으며 다음과 같은 흥미로운 정보를 얻었습니다.

<CalculatorList>
  <FilterCalculator CalculatorName="CSelCalcColumnInInterval" Selectivity="-1.000" 
                    CalculatorFailed="true" TableName="[p]" ColumnName="CommentCount" />

  <FilterCalculator CalculatorName="CSelCalcAscendingKeyFilter" Selectivity="0.001" 
                    TableName="[p]" ColumnName="CommentCount" UseAverageFrequency="true" 
                    StatId="4" />
</CalculatorList>

그래서 그것은 CSelCalcAscendingKeyFilter계산기가 사용 된 것처럼 보입니다 (다른 계산기는 그것이 무엇이든간에 실패했다고 말합니다). 이 열은 키가 아니거나 고유하거나 반드시 오름차순이지만 아무 것도 아닙니다.

해당 용어를 인터넷 검색하면 블로그 게시물로 연결됩니다.

이 게시물은 새로운 CE가 히스토그램 외부 추정치에서 밀도 벡터와 통계 수정 카운터의 조합을 기반으로 함을 나타냅니다. 불행히도, 나는 이미 밀도 벡터를 배제했습니다 (생각합니까?!). 수정 카운터는 0입니다 ( sys.dm_db_stats_properties어쨌든 당 ).

추적 플래그

포레스트 는 추정 과정에 대한 더 많은 정보를 얻기 위해 TF 2363을 켤 것을 제안했다. 그 출력에서 ​​가장 관련이 있다고 생각합니다.

Plan for computation:

  CSelCalcAscendingKeyFilter(avg. freq., QCOL: [p].CommentCount)

Selectivity: 0.000516798

이것은 획기적인 것입니다 (감사합니다, 포레스트!) : 그 0.000516798숫자 ( Selectivity="0.001"위 의 XE 속성 에서 도움이되지 않은 것으로 보입니다 )에 표의 행 수를 곱한 것은 내가 찾은 추정치입니다 (1,934.99).

아마도 분명한 것이 빠져있을 수도 있지만 CSelCalcAscendingKeyFilter계산기에서 선택성 값이 어떻게 생성되는지 리버스 엔지니어링 할 수 없었습니다 .

답변:


13

내 테스트에 따르면 범위를 벗어난 카디널리티 추정치는 단순히 행 수의 제곱근이며 마지막 통계 업데이트 이후 추가 된 행 수로 아래에 묶여 있으며 값 당 평균 행으로 위에 묶입니다.

귀하의 경우 1,934.99 = SQRT (3744192)

아래 테스트 설정 :

--setup
USE TestDB
ALTER DATABASE [TestDB] SET AUTO_UPDATE_STATISTICS OFF
GO

DROP TABLE IF EXISTS dbo.Hist

CREATE TABLE dbo.Hist (
ID int identity primary key,
Num int
)

INSERT dbo.Hist
SELECT TOP 300
(ROW_NUMBER() OVER(ORDER BY(SELECT 1/0)))%3
FROM master..spt_values a
CROSS JOIN master..spt_values b
--Get estimated plan
--don't forget to run right after setup to auto-create stats
SELECT *
FROM dbo.Hist
WHERE Num = 1000
--gradually add rows, then rerun estimate above
INSERT dbo.Hist
SELECT TOP 100
-1
FROM master..spt_values a
--I sure hope you weren't testing this in prod (cleanup)
ALTER DATABASE [TestDB] SET AUTO_UPDATE_STATISTICS ON
GO

놀랍게도이 접근 방식으로 행 추정치가 생성되었습니다 : 총 400 행에서 20, 900에서 30, 1600에서 40 등.

그러나 10000을 지나서 행 추정치는 100에서 최대 값이며, 이는 기존 통계의 값당 행 수입니다. sqrt (300)> 10이므로 10 개의 행만 추가하면 추정값이 10으로 설정됩니다.

따라서이 공식을 사용하여 추정치를 표현할 수 있습니다.

Estimate = MIN(SQRT(AC), MIN(AR, MC))

통계가 샘플링되면 MC가 고려되지 않습니다. 따라서 공식은 다음과 같습니다.

Estimate = MIN(SQRT(AC), AR))

어디

  • MC는 "수정 횟수"(통계가 작성된 이후 수정 횟수)입니다.
  • AC는 "조정 된 카디널리티"(통계와 MC의 행 수)입니다.
  • AR은 값당 평균 행 (통계의 행 수를 열의 고유 값으로 나눈 값)입니다.

이 추정값에 대한 공식 및 계산기에 대한 기타 세부 사항은이 블로그 게시물에서 찾을 수 있습니다 . CSelCalcAscendingKeyFilter 계산기의 추정치 분석

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