쿼리 창에서 2 초 안에 실행되는 복잡한 쿼리가 있지만 저장 프로 시저로 약 5 분이 걸립니다. 저장 프로 시저로 실행하는 데 시간이 오래 걸리는 이유는 무엇입니까?
내 쿼리는 다음과 같습니다.
특정 레코드 세트 ( @id
및로 식별 됨 @createdDate
) 및 특정 기간 (에서 시작하여 1 년)을 취하고 @startDate
해당 문자의 결과로 수신 된 문자 및 예상 지불의 요약 된 목록을 리턴합니다.
CREATE PROCEDURE MyStoredProcedure
@id int,
@createdDate varchar(20),
@startDate varchar(20)
AS
SET NOCOUNT ON
-- Get the number of records * .7
-- Only want to return records containing letters that were sent on 70% or more of the records
DECLARE @limit int
SET @limit = IsNull((SELECT Count(*) FROM RecordsTable WITH (NOLOCK) WHERE ForeignKeyId = @id AND Created = @createdDate), 0) * .07
SELECT DateSent as [Date]
, LetterCode as [Letter Code]
, Count(*) as [Letters Sent]
, SUM(CASE WHEN IsNull(P.DatePaid, '1/1/1753') BETWEEN DateSent AND DateAdd(day, 30, DateSent) THEN IsNull(P.TotalPaid, 0) ELSE 0 END) as [Amount Paid]
INTO #tmpTable
FROM (
-- Letters Table. Filter for specific letters
SELECT DateAdd(day, datediff(day, 0, LR.DateProcessed), 0) as [DateSent] -- Drop time from datetime
, LR.LetterCode -- Letter Id
, M.RecordId -- Record Id
FROM LetterRequest as LR WITH (NOLOCK)
INNER JOIN RecordsTable as M WITH (NOLOCK) ON LR.RecordId = M.RecordId
WHERE ForeignKeyId = @id AND Received = @createdDate
AND LR.Deleted = 0 AND IsNull(LR.ErrorDescription, '') = ''
AND LR.DateProcessed BETWEEN @startDate AND DateAdd(year, 1, @startDate)
AND LR.LetterCode IN ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o')
) as T
LEFT OUTER JOIN (
-- Payment Table. Payments that bounce are entered as a negative payment and are accounted for
SELECT PH.RecordId, PH.DatePaid, PH.TotalPaid
FROM PaymentHistory as PH WITH (NOLOCK)
INNER JOIN RecordsTable as M WITH (NOLOCK) ON PH.RecordId = M.RecordId
LEFT OUTER JOIN PaymentHistory as PR WITH (NOLOCK) ON PR.ReverseOfUId = PH.UID
WHERE PH.SomeString LIKE 'P_'
AND PR.UID is NULL
AND PH.DatePaid BETWEEN @startDate AND DateAdd(day, 30, DateAdd(year, 1, @startDate))
AND M.ForeignKeyId = @id AND M.Created = @createdDate
) as P ON T.RecordId = P.RecordId
GROUP BY DateSent, LetterCode
--HAVING Count(*) > @limit
ORDER BY DateSent, LetterCode
SELECT *
FROM #tmpTable
WHERE [Letters Sent] > @limit
DROP TABLE #tmpTable
최종 결과는 다음과 같습니다.
날짜 문자 코드 문자 보낸 금액 지불 2012 년 1 월 1 일 1245 12345.67 2012 년 1 월 1 일 b 2301 1234.56 2012 년 1 월 1 일 c 1312 7894.45 2012 년 1 월 1 일 1455 2345.65 2012 년 1 월 1 일 c 3611 3213.21
쿼리 편집기에서 모든 것이 매우 빠르게 실행되기 때문에 속도 저하 위치를 파악하는 데 문제가 있습니다. 쿼리를 저장 프로 시저로 이동하여 실행하는 데 시간이 오래 걸리는 경우에만 가능합니다.
쿼리 실행 계획이 생성되는 것과 관련이 있다고 확신하지만 SQL에 대해 문제를 일으키는 원인을 식별하기에 충분하지 않습니다.
쿼리에 사용 된 모든 테이블에는 수백만 개의 레코드가 있습니다.
누군가 쿼리 편집기에서보다 저장 프로 시저로 실행하는 데 시간이 오래 걸리는 이유를 설명하고 저장 프로 시저로 실행할 때 성능 문제를 일으킬 수있는 쿼리의 일부를 식별 할 수 있습니까?
RECOMPILE
쿼리가 실행될 때마다 다시 컴파일하고 싶지 않기 때문에 힌트 를 피하고 싶습니다. 링크 된 기사는 매개 변수를 로컬 변수에 복사하는 것이 사용하는 것과 동일하다고 언급OPTIMIZE FOR UNKNOWN
했습니다. 2008 이상. 지금은 매개 변수를 로컬 변수에 복사하여 쿼리 실행 시간을 1-2 초로 줄이겠다 고 생각합니다.