레거시 CE로 SQL Server 2014에서 테스트했으며 카디널리티 추정치로 9 %를 얻지 못했습니다. 온라인에서 정확한 것을 찾을 수 없어서 몇 가지 테스트를 해본 결과 시도한 모든 테스트 사례에 맞는 모델을 찾았지만 그것이 완료되었는지 확신 할 수 없습니다.
내가 찾은 모델에서 추정치는 테이블의 행 수, 필터링 된 열에 대한 통계의 평균 키 길이 및 때로는 필터링 된 열의 데이터 유형 길이에서 파생됩니다. 추정에 사용되는 두 가지 다른 공식이 있습니다.
FLOOR (평균 키 길이) = 0이면 추정 공식은 열 통계를 무시하고 데이터 유형 길이를 기반으로 추정을 작성합니다. VARCHAR (N)으로 만 테스트 했으므로 NVARCHAR (N)에 대해 다른 수식이있을 수 있습니다. VARCHAR (N)의 공식은 다음과 같습니다.
(행 추정) = (표의 행) * (-0.004869 + 0.032649 * log10 (데이터 유형의 길이))
이것은 매우 잘 맞지만 완벽하게 정확하지는 않습니다.
x 축은 데이터 유형의 길이이고 y 축은 1 백만 개의 행이있는 테이블의 예상 행 수입니다.
열에 대한 통계가 없거나 열에 평균 키 길이가 1 미만이되도록 충분한 NULL 값이있는 경우 쿼리 최적화 프로그램에서이 수식을 사용합니다.
예를 들어, VARCHAR (50)에서 필터링하고 열 통계가없는 150k 개의 행이있는 테이블이 있다고 가정하십시오. 행 추정 예측은 다음과 같습니다.
150000 * (-0.004869 + 0.032649 * log10 (50)) = 7590.1 행
그것을 테스트하는 SQL :
CREATE TABLE X_CE_LIKE_TEST_1 (
STRING VARCHAR(50)
);
CREATE STATISTICS X_STAT_CE_LIKE_TEST_1 ON X_CE_LIKE_TEST_1 (STRING) WITH NORECOMPUTE;
WITH
L0 AS (SELECT 1 AS c UNION ALL SELECT 1),
L1 AS (SELECT 1 AS c FROM L0 A CROSS JOIN L0 B),
L2 AS (SELECT 1 AS c FROM L1 A CROSS JOIN L1 B),
L3 AS (SELECT 1 AS c FROM L2 A CROSS JOIN L2 B),
L4 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L3 B CROSS JOIN L2 C),
NUMS AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS NUM FROM L4)
INSERT INTO X_CE_LIKE_TEST_1 WITH (TABLOCK) (STRING)
SELECT TOP (150000) 'ZZZZZ'
FROM NUMS
ORDER BY NUM;
DECLARE @LastName VARCHAR(15) = 'BA%'
SELECT * FROM X_CE_LIKE_TEST_1
WHERE STRING LIKE @LastName;
SQL Server는 7242.47의 예상 행 수를 제공합니다.
FLOOR (평균 키 길이)> = 1 인 경우 FLOOR (평균 키 길이) 값을 기반으로하는 다른 수식이 사용됩니다. 다음은 내가 시도한 일부 값의 표입니다.
1 1.5%
2 1.5%
3 1.64792%
4 2.07944%
5 2.41416%
6 2.68744%
7 2.91887%
8 3.11916%
9 3.29584%
10 3.45388%
FLOOR (평균 키 길이) <6 인 경우 위 표를 사용하십시오. 그렇지 않으면 다음 방정식을 사용하십시오.
(행 추정) = (표의 행) * (-0.003381 + 0.034539 * log10 (FLOOR (평균 키 길이)))
이것은 다른 것보다 더 잘 맞지만 여전히 완벽하게 정확하지는 않습니다.
x 축은 평균 키 길이이고 y 축은 1 백만 행이있는 테이블의 예상 행 수입니다.
다른 예를 제공하기 위해 필터링 된 열의 통계에 대해 평균 키 길이가 5.5 인 행이 10k 인 테이블이 있다고 가정하십시오. 행 추정치는 다음과 같습니다.
10000 * 0.241416 = 241.416 행.
그것을 테스트하는 SQL :
CREATE TABLE X_CE_LIKE_TEST_2 (
STRING VARCHAR(50)
);
WITH
L0 AS (SELECT 1 AS c UNION ALL SELECT 1),
L1 AS (SELECT 1 AS c FROM L0 A CROSS JOIN L0 B),
L2 AS (SELECT 1 AS c FROM L1 A CROSS JOIN L1 B),
L3 AS (SELECT 1 AS c FROM L2 A CROSS JOIN L2 B),
L4 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L3 B CROSS JOIN L2 C),
NUMS AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS NUM FROM L4)
INSERT INTO X_CE_LIKE_TEST_2 WITH (TABLOCK) (STRING)
SELECT TOP (10000)
CASE
WHEN NUM % 2 = 1 THEN REPLICATE('Z', 5)
ELSE REPLICATE('Z', 6)
END
FROM NUMS
ORDER BY NUM;
CREATE STATISTICS X_STAT_CE_LIKE_TEST_2 ON X_CE_LIKE_TEST_2 (STRING)
WITH NORECOMPUTE, FULLSCAN;
DECLARE @LastName VARCHAR(15) = 'BA%'
SELECT * FROM X_CE_LIKE_TEST_2
WHERE STRING LIKE @LastName;
행 추정치는 241.416이며 질문에있는 것과 일치합니다. 테이블에없는 값을 사용하면 약간의 오류가 발생합니다.
이 모델은 완벽하지는 않지만 일반적인 동작을 잘 보여줍니다.