현재까지 캐스팅의 sargability 뒤에있는 메커니즘을 dynamic seek 라고 합니다.
SQL Server는 내부 함수 GetRangeThroughConvert
를 호출 하여 범위의 시작과 끝을 얻습니다.
놀랍게도 이것은 리터럴 값과 같은 범위 가 아닙니다 .
페이지 당 행과 하루 1440 행으로 테이블 작성
CREATE TABLE T
(
DateTimeCol DATETIME PRIMARY KEY,
Filler CHAR(8000) DEFAULT 'X'
);
WITH Nums(Num)
AS (SELECT number
FROM spt_values
WHERE type = 'P'
AND number BETWEEN 1 AND 1440),
Dates(Date)
AS (SELECT {d '2012-12-30'} UNION ALL
SELECT {d '2012-12-31'} UNION ALL
SELECT {d '2013-01-01'} UNION ALL
SELECT {d '2013-01-02'} UNION ALL
SELECT {d '2013-01-03'})
INSERT INTO T
(DateTimeCol)
SELECT DISTINCT DATEADD(MINUTE, Num, Date)
FROM Nums,
Dates
그런 다음 실행
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
SELECT *
FROM T
WHERE DateTimeCol >= '20130101'
AND DateTimeCol < '20130102'
SELECT *
FROM T
WHERE CAST(DateTimeCol AS DATE) = '20130101';
첫 번째 쿼리는 1443
읽기를 수행하고 두 번째 쿼리는 2883
전체 추가 날짜를 읽은 다음 잔여 술어에 대해 버립니다.
계획은 탐색 술어가
Seek Keys[1]: Start: DateTimeCol > Scalar Operator([Expr1006]),
End: DateTimeCol < Scalar Operator([Expr1007])
따라서 대신 모든 행을 >= '20130101' ... < '20130102'
읽고 > '20121231' ... < '20130102'
버립니다 2012-12-31
.
이에 의존하는 또 다른 단점은 카디널리티 추정이 기존 범위 쿼리보다 정확하지 않을 수 있다는 것입니다. 이것은 수정 된 버전의 SQL Fiddle 에서 볼 수 있습니다 .
테이블의 100 개 행이 모두 술어와 일치합니다 (날짜 시간이 같은 날 1 분 간격으로).
두 번째 (범위) 쿼리는 100이 일치하고 클러스터형 인덱스 스캔을 사용할 것으로 정확하게 추정합니다. CAST( AS DATE)
쿼리는 잘못 하나의 행이 일치 할 것으로 추정 및 키 조회와 계획을 생성합니다.
통계는 완전히 무시되지 않습니다. 테이블의 모든 행이 동일 datetime
하고 술어와 일치하는 경우 (예 : 20130101 00:00:00
또는 20130101 01:00:00
) 계획에 31.6228 행이있는 클러스터 된 인덱스 스캔이 표시됩니다.
100 ^ 0.75 = 31.6228
따라서이 경우 추정치는 여기 공식에서 파생 된 것으로 보입니다 .
테이블의 모든 행이 동일 datetime
하고 술어와 일치하지 않으면 (예 :) 20130102 01:00:00
예상 행 수 1 및 계획이있는 계획으로 돌아갑니다.
테이블에 둘 이상의 DISTINCT
값이있는 경우 예상 행은 쿼리가 정확하게 찾은 것과 같은 것으로 보입니다 20130101 00:00:00
.
통계 히스토그램에 단계가있는 2013-01-01 00:00:00.000
경우 추정치는 EQ_ROWS
(즉, 해당 날짜의 다른 시간은 고려하지 않음)을 기준으로합니다. 그렇지 않으면 단계가 없으면 AVG_RANGE_ROWS
주변 단계에서를 사용하는 것처럼 보입니다 .
으로 datetime
많은 시스템에서 약 3MS의 정밀도를 가지고이 거의 실제 중복 값이 될 것이며,이 숫자는 1이됩니다.