설정
카디널리티 예상을 이해하는 데 문제가 있습니다. 테스트 설정은 다음과 같습니다.
- 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]);
그 하이라이트는 다음과 같습니다.
- 통계는 1.81 % (67,796 / 3,744,192)의 샘플링 속도가 매우 낮습니다.
- 31 개의 히스토그램 단계 만 사용되었습니다
- "모든 밀도"값은
0.03030303
(33 개의 개별 값이 샘플링 됨) RANGE_HI_KEY
히스토그램 의 마지막 은 50EQ_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
계산기에서 선택성 값이 어떻게 생성되는지 리버스 엔지니어링 할 수 없었습니다 .