मेरे पास एक जटिल क्वेरी है जो क्वेरी विंडो में 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
अंतिम परिणाम इस तरह दिखता है:
दिनांक पत्र कोड पत्र भेजे गए राशि का भुगतान 1/1/2012 एक 1245 12345.67 1/1/2012 बी 2301 1234.56 1/1/2012 c 1312 7894.45 1/1/2012 एक 1455 2345.65 1/1/2012 c 3611 3213.21
मुझे यह पता लगाने में समस्या हो रही है कि मंदी कहाँ है, क्योंकि क्वेरी एडिटर में सब कुछ बहुत तेज़ चलता है। यह केवल तभी होता है जब मैं क्वेरी को एक संग्रहीत प्रक्रिया में ले जाता हूं, जिसे चलाने में इतना लंबा समय लगता है।
मुझे यकीन है कि यह क्वेरी निष्पादन योजना उत्पन्न करने के साथ कुछ करने के लिए है, लेकिन मुझे एसक्यूएल के बारे में पर्याप्त नहीं पता है कि समस्या का कारण क्या हो सकता है।
यह संभवतः ध्यान दिया जाना चाहिए कि क्वेरी में प्रयुक्त सभी तालिकाओं में लाखों रिकॉर्ड हैं।
क्या कोई मुझे समझा सकता है कि यह क्वेरी संपादक की तुलना में संग्रहीत प्रक्रिया के रूप में चलाने में इतना अधिक समय क्यों ले रहा है, और मुझे यह पहचानने में मदद करता है कि संग्रहीत प्रक्रिया के रूप में चलने पर मेरे क्वेरी का कौन सा भाग प्रदर्शन समस्याओं का कारण बन सकता है?
RECOMPILE
संकेत से बचना पसंद करूँगा क्योंकि मैं वास्तव में हर बार चलने वाली क्वेरी को फिर से प्राप्त नहीं करना चाहता हूं, और आपके द्वारा लिंक किए गए लेख ने उल्लेख किया है कि एक स्थानीय चर में मापदंडों की नकल करना उपयोग करने के बराबर हैOPTIMIZE FOR UNKNOWN
, जो केवल में उपलब्ध लगता है। 2008 और बाद में। मुझे लगता है कि अब मैं मापदंडों को एक स्थानीय चर में कॉपी करने के साथ रहूंगा, जो मेरे क्वेरी निष्पादन समय को 1-2 सेकंड तक नीचे लाता है।