쿼리는
SELECT SUM(Amount) AS SummaryTotal
FROM PDetail WITH(NOLOCK)
WHERE ClientID = @merchid
AND PostedDate BETWEEN @datebegin AND @dateend
테이블에는 103,129,000 개의 행이 있습니다.
빠른 계획은 날짜에 잔류 술어가있는 ClientId가 조회하지만을 검색하려면 96 개의 조회를 수행해야합니다 Amount
. <ParameterList>
계획 의 섹션은 다음과 같습니다.
<ParameterList>
<ColumnReference Column="@dateend"
ParameterRuntimeValue="'2013-02-01 23:59:00.000'" />
<ColumnReference Column="@datebegin"
ParameterRuntimeValue="'2013-01-01 00:00:00.000'" />
<ColumnReference Column="@merchid"
ParameterRuntimeValue="(78155)" />
</ParameterList>
느린 계획은 날짜별로 조회되며 ClientId의 잔여 술어를 평가하고 금액을 검색하기 위해 조회합니다 (예상 1 대 실제 7,388,383). <ParameterList>
섹션입니다
<ParameterList>
<ColumnReference Column="@EndDate"
ParameterCompiledValue="'2013-02-01 23:59:00.000'"
ParameterRuntimeValue="'2013-02-01 23:59:00.000'" />
<ColumnReference Column="@BeginDate"
ParameterCompiledValue="'2013-01-01 00:00:00.000'"
ParameterRuntimeValue="'2013-01-01 00:00:00.000'" />
<ColumnReference Column="@ClientID"
ParameterCompiledValue="(78155)"
ParameterRuntimeValue="(78155)" />
</ParameterList>
두 번째 경우에는 ParameterCompiledValue
것입니다 하지 빈. SQL Server가 쿼리에 사용 된 값을 스니핑했습니다.
"SQL Server 2005 실용 문제 해결" 책 에는 로컬 변수 사용에 대한 내용이 있습니다.
매개 변수 스니핑을 물리 치기 위해 로컬 변수를 사용하는 것은 상당히 일반적인 트릭이지만 힌트 OPTION (RECOMPILE)
와 OPTION (OPTIMIZE FOR)
힌트는 일반적으로보다 우아하고 덜 위험합니다.
노트
SQL Server 2005에서 명령문 수준 컴파일을 사용하면 쿼리를 처음 실행하기 직전까지 저장 프로 시저의 개별 명령문 컴파일을 연기 할 수 있습니다. 그때까지 지역 변수의 값을 알 수 있습니다. 이론적으로 SQL Server는이를 활용하여 매개 변수를 스니핑하는 것과 같은 방식으로 로컬 변수 값을 스니핑 할 수 있습니다. 그러나 SQL Server 7.0 및 SQL Server 2000+에서 매개 변수 스니핑을 막기 위해 로컬 변수를 사용하는 것이 일반적이기 때문에 SQL Server 2005에서는 로컬 변수 스니핑을 사용할 수 없었습니다. 향후 SQL Server 릴리스에서 사용 가능할 수도 있습니다. 선택의 여지가 있다면이 장에 요약 된 다른 옵션 중 하나를 사용해야하는 이유.
빠른 테스트 에서이 목적은 2008 년과 2012 년에도 동일하게 유지되며 지연 컴파일을 위해 변수가 스니핑되지 않고 명시 적 OPTION RECOMPILE
힌트가 사용될 때만 스니핑 됩니다.
DECLARE @N INT = 0
CREATE TABLE #T ( I INT );
/*Reference to #T means this statement is subject to deferred compile*/
SELECT *
FROM master..spt_values
WHERE number = @N
AND EXISTS(SELECT COUNT(*) FROM #T)
SELECT *
FROM master..spt_values
WHERE number = @N
OPTION (RECOMPILE)
DROP TABLE #T
지연된 컴파일에도 불구하고 변수가 스니핑되지 않고 예상 행 수가 정확하지 않습니다.
따라서 느린 계획은 매개 변수화 된 버전의 쿼리와 관련이 있다고 가정합니다.
는 ParameterCompiledValue
같다 ParameterRuntimeValue
이 (계획 값이어서 다른 세트의 실행을위한 한 세트의 값에 대한 컴파일 된) 스니핑 대표적인 파라미터가되지 않도록 모든 파라미터에 대한.
문제는 올바른 매개 변수 값을 위해 컴파일 된 계획이 부적절하다는 것입니다.
여기 및 여기에 설명 된 오름차순으로 문제가 발생했을 수 있습니다 . 1 억 개의 행이있는 테이블의 경우 SQL Server가 자동으로 통계를 업데이트하기 전에 2 천만을 삽입하거나 수정해야합니다. 지난 번에 업데이트 된 행은 쿼리의 날짜 범위와 일치했지만 현재는 7 백만입니다.
보다 빈번한 통계 업데이트를 예약 2389 - 90
하거나 추적 플래그를 고려 하거나 사용 OPTIMIZE FOR UKNOWN
하여 datetime
열 에서 현재 오해의 소지가있는 통계를 사용할 수있는 것보다는 추측으로 돌아갑니다 .
다음 버전의 SQL Server (2012 이후)에는 필요하지 않을 수 있습니다. 관련 연결 항목은 흥미로운 반응을 포함
Microsoft가 2012 년 8 월 28 일 오후 1시 35 분에 게시 함
우리는이 문제를 근본적으로 해결하는 다음 주요 릴리스에 대한 카디널리티 추정 향상을 수행했습니다. 미리보기가 나오면 자세한 내용을 확인하십시오. 에릭
이 2014의 개선점은 Benjamin Nevarez가 기사의 끝 부분을 살펴 보았습니다.
새 SQL 서버 리티 견적에서의 첫 봐 .
새로운 카디널리티 추정기는이 경우 1 행 추정값을 제공하는 대신 폴백하고 평균 밀도를 사용하는 것으로 보입니다.
2014 카디널리티 추정기 및 오름차순 주요 문제에 대한 추가 정보는 다음과 같습니다.
SQL Server 2014의 새로운 기능 – 2 부 – 새로운 카디널리티 예상