문제

직장에서 새 쿼리를 개발하는 동안 나는 그것을 작성하고 SQL 쿼리 분석기로 프로파일 링했습니다. 쿼리는 테이블 스캔없이 정말 좋은 성능을 발휘했지만 저장된 절차 내에서 캡슐화했을 때 성능은 끔찍했습니다. 실행 계획을 살펴 보았을 때 SQL Server가 TableB에서 인덱스 찾기 대신 테이블 스캔을 사용한 다른 계획을 선택했음을 알 수있었습니다 (테이블과 열 이름을 약간 난독 화해야했지만 쿼리 로직은 없습니다. 변경되었습니다).

다음은 쿼리입니다

SELECT     
    DATEADD(dd, 0, DATEDIFF(dd, 0, TableA.Created)) AS Day, 
    DATEPART(hh, TableA.Created) AS [Hour], 
    SUM(TableB.Quantity) AS Quantity, 
    SUM(TableB.Amount) AS Amount
FROM
    TableA
    INNER JOIN TableB ON TableA.BID = TableB.ID
WHERE     
    (TableA.ShopId = @ShopId)
GROUP BY 
    DATEADD(dd, 0, DATEDIFF(dd, 0, TableA.Created)), 
    DATEPART(hh, TableA.Created)
ORDER BY 
    DATEPART(hh, TableA.Created)

쿼리 "aw"를 실행하면 다음 추적 통계가 있습니다.

Event Class         Duration  CPU  Reads Writes
SQL:StmtCompleted   75        41      7      0

그리고 다음 명령을 사용하여 쿼리를 저장된 Proc로 실행할 때

DECLARE @ShopId int
SELECT @ShopId = 1
EXEC spStats_GetSalesStatsByHour @ShopId

나는 다음과 같은 트레이스 통계를받습니다

Event Class         Duration  CPU  Reads Writes
SQL:StmtCompleted   222       10     48      0

또한 쿼리를 nvarchar에 저장하고 SP_ExecutesQL을 사용하여 이와 같이 실행하면 동일한 결과를 얻습니다 (Sproc처럼 수행).

DECLARE @SQL nvarchar(2000)
SET @SQL = 'SELECT DATEADD(dd, ...'
exec sp_executesql @SQL

저장된 절차에는 위의 일부 명령문을 제외하고는 아무것도 포함하지 않습니다. 명세서가 저장 프로 시저로 실행되기 때문에 SQL Server가 열등한 실행 계획을 선택하게하는 원인은 무엇입니까?

우리는 현재 실행 중입니다 SQL Server 2000

도움이 되었습니까?

해결책

이것은 일반적으로 매개 변수 스니핑과 관련이 있습니다. 다루는 것은 매우 실망 스러울 수 있습니다. 때로는 저장된 절차를 다시 컴파일하여 해결할 수 있으며 때로는 저장된 절차 내에서 중복 변수를 사용할 수도 있습니다.

alter procedure p_myproc (@p1 int) as
declare @p1_copy int;
set @p1_copy = @p1;

그런 다음 쿼리에서 @p1_copy를 사용하십시오. 말도 안되는 것처럼 보이지만 작동합니다.

동일한 주제에 대한 최근 질문을 확인하십시오.

SQLServer Optimizer가 왜 매개 변수와 혼동 되는가?

다른 팁

예 - Oracle DB 11G에서도 이것을 보았습니다. SQL 프롬프트에서 DB 서버의 2 개 노드에서 같은 쿼리가 빠르게 진행되었지만 패키지에서 호출하면 문자 그대로 끊었습니다!

동일한 동작을 얻으려면 공유 풀을 지워야했습니다. 이유가 열등한 실행 계획이있는 하나의 노드에서 라이브러리 캐시/메모리에 오래된 사본이 잠겨있는 일부 작업/스크립트가 실행 중입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top