SQL सर्वर: क्वेरी तेज़, लेकिन प्रक्रिया से धीमी


257

एक क्वेरी तेजी से चलती है:

DECLARE @SessionGUID uniqueidentifier
SET @SessionGUID = 'BCBA333C-B6A1-4155-9833-C495F22EA908'

SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

उप लागत: 0.502

लेकिन एक ही SQL को एक संग्रहीत कार्यविधि में डालना धीमी गति से चलता है, और पूरी तरह से अलग निष्पादन योजना के साथ

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS
SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

EXECUTE ViewOpener @SessionGUID

सबट्री कॉस्ट: 19.2

मैं चला हूं

sp_recompile ViewOpener

और यह अभी भी (बुरी तरह से) चलाता है, और मैंने भी संग्रहीत प्रक्रिया को बदल दिया है

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS
SELECT *, 'recompile please'
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

और वापस फिर से, वास्तव में इसे recompiling में चाल की कोशिश कर रहा है।

मैंने एक नई योजना तैयार करने के लिए संग्रहीत कार्यविधि को गिरा दिया है और फिर से बनाया है।

मैं recompiles मजबूर करने की कोशिश की है, और एक सूंघ चर का उपयोग करके पैरामीटर सूँघने को रोकने के लिए :

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS

DECLARE @SessionGUIDbitch uniqueidentifier
SET @SessionGUIDbitch = @SessionGUID

SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUIDbitch
ORDER BY CurrencyTypeOrder, Rank

मैंने भी संग्रहीत प्रक्रिया को परिभाषित करने की कोशिश की है WITH RECOMPILE:

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier 
WITH RECOMPILE
AS
SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

ताकि यह योजना कभी भी कैश न हो, और मैंने निष्पादित करने के लिए मजबूर करने की कोशिश की है:

EXECUTE ViewOpener @SessionGUID WITH RECOMPILE

जो मदद नहीं की।

मैंने प्रक्रिया को गतिशील SQL में बदलने की कोशिश की है:

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier 
WITH RECOMPILE AS
DECLARE @SQLString NVARCHAR(500)

SET @SQLString = N'SELECT *
   FROM Report_OpenerTest
   WHERE SessionGUID = @SessionGUID
   ORDER BY CurrencyTypeOrder, Rank'

EXECUTE sp_executesql @SQLString,
N'@SessionGUID uniqueidentifier',
@SessionGUID

जो मदद नहीं की।

इकाई " Report_Opener" एक दृश्य है, जिसे अनुक्रमित नहीं किया गया है। दृश्य केवल अंतर्निहित तालिकाओं का संदर्भ देता है। किसी तालिका में संगणित कॉलम, अनुक्रमित या अन्यथा शामिल नहीं हैं।

यह नरक के लिए मैं के साथ दृश्य बनाने की कोशिश की

SET ANSI_NULLS ON
SET QUOTED_IDENTIFER ON

यह तय नहीं किया।

वह कैसा है?

  • क्वेरी तेज है
  • क्वेरी को किसी दृश्य में ले जाना, और दृश्य से चयन करना तेज़ है
  • संग्रहीत कार्यविधि से दृश्य से चयन करना 40x धीमा है?

मैंने दृश्य की परिभाषा को सीधे संग्रहीत प्रक्रिया में स्थानांतरित करने की कोशिश की (3 व्यावसायिक नियमों का उल्लंघन, और एक महत्वपूर्ण एनकैप्सुलेशन को तोड़ना), और यह केवल लगभग 6x धीमी बनाता है।

संग्रहित प्रक्रिया संस्करण इतना धीमा क्यों है? एक अलग तरह के ऐड-हॉक एसक्यूएल की तुलना में एसक्यूएल सर्वर पर चलने वाले एसक्यूएल सर्वर के लिए क्या संभव है?

मैं वास्तव में नहीं हूँ

  • कोड में SQL एम्बेड करें
  • कोड को बिल्कुल बदल दें

    Microsoft SQL Server  2000 - 8.00.2050 (Intel X86)
    Mar  7 2008 21:29:56
    Copyright (c) 1988-2003 Microsoft Corporation
    Standard Edition on Windows NT 5.2 (Build 3790: Service Pack 2)
    

लेकिन एसक्यूएल सर्वर के रूप में तेजी से चलाने में असमर्थ होने के कारण क्या हो सकता है कि एसक्यूएल सेटर एक क्वेरी चला रहा है, अगर पैरामीटर सूँघ नहीं रहा है।


मेरा अगला प्रयास करने के लिए किया जाएगा StoredProcedureAकॉल StoredProcedureBकॉल StoredProcedureCकॉल StoredProcedureDदृश्य क्वेरी करने के लिए।

और इसमें विफल होने पर, संग्रहीत कार्यविधि को संग्रहीत कार्यविधि कहा जाता है, UDF को कॉल करें, UDF को कॉल करें, संग्रहीत कार्यविधि को कॉल करें, दृश्य को क्वेरी करने के लिए UDF को कॉल करें।


संक्षेप में, निम्नलिखित क्यूए से तेजी से चलता है, लेकिन एक संग्रहीत प्रक्रिया में डालने पर धीमा:

असली:

--Runs fine outside of a stored procedure
SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

sp_executesql:

--Runs fine outside of a stored procedure
DECLARE @SQLString NVARCHAR(500)
SET @SQLString = N'SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank'

EXECUTE sp_executesql @SQLString,
        N'@SessionGUID uniqueidentifier',
        @SessionGUID

EXEC(@sql):

--Runs fine outside of a stored procedure
DECLARE @sql NVARCHAR(500)
SET @sql = N'SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = '''+CAST(@SessionGUID AS varchar(50))+'''
ORDER BY CurrencyTypeOrder, Rank'

EXEC(@sql)

निष्पादन योजनाएं

अच्छा योजना:

      |--Sort(ORDER BY:([Expr1020] ASC, [Currencies].[Rank] ASC))
           |--Compute Scalar(DEFINE:([Expr1020]=If ([Currencies].[CurrencyType]='ctCanadianCash') then 1 else If ([Currencies].[CurrencyType]='ctMiscellaneous') then 2 else If ([Currencies].[CurrencyType]='ctTokens') then 3 else If ([Currencies].[CurrencyType]
                |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Openers].[OpenerGUID]))
                     |--Filter(WHERE:((([Currencies].[IsActive]<>0 AND [Currencies].[OnOpener]<>0) AND ((((((([Currencies].[CurrencyType]='ctUSCoin' OR [Currencies].[CurrencyType]='ctMiscellaneousUS') OR [Currencies].[CurrencyType]='ctUSCash') OR [Currencies].
                     |    |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Currencies].[CurrencyGUID], [Openers].[OpenerGUID]) WITH PREFETCH)
                     |         |--Nested Loops(Left Outer Join)
                     |         |    |--Bookmark Lookup(BOOKMARK:([Bmk1016]), OBJECT:([GrobManagementSystemLive].[dbo].[Windows]))
                     |         |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([Openers].[WindowGUID]))
                     |         |    |         |--Bookmark Lookup(BOOKMARK:([Bmk1014]), OBJECT:([GrobManagementSystemLive].[dbo].[Openers]))
                     |         |    |         |    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_SessionGUID]), SEEK:([Openers].[SessionGUID]=[@SessionGUID]) ORDERED FORWARD)
                     |         |    |         |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Windows].[IX_Windows]), SEEK:([Windows].[WindowGUID]=[Openers].[WindowGUID]) ORDERED FORWARD)
                     |         |    |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                     |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID] AND [OpenerDetails].[CurrencyGUID]=[Currenc
                     |--Hash Match(Cache, HASH:([Openers].[OpenerGUID]), RESIDUAL:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]))
                          |--Stream Aggregate(DEFINE:([Expr1006]=SUM(If (((([Currencies].[CurrencyType]='ctMiscellaneous' OR [Currencies].[CurrencyType]='ctTokens') OR [Currencies].[CurrencyType]='ctChips') OR [Currencies].[CurrencyType]='ctCanadianCoin') OR [
                               |--Nested Loops(Inner Join, OUTER REFERENCES:([OpenerDetails].[CurrencyGUID]) WITH PREFETCH)
                                    |--Nested Loops(Inner Join)
                                    |    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_OneOpenerPerSession]), SEEK:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                    |    |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[PK_Currencies_CurrencyGUID]), SEEK:([Currencies].[CurrencyGUID]=[OpenerDetails].[CurrencyGUID]) ORDERED FORWARD)

बुरा योजना

       |--Sort(ORDER BY:([Expr1020] ASC, [Currencies].[Rank] ASC))
            |--Compute Scalar(DEFINE:([Expr1020]=If ([Currencies].[CurrencyType]='ctCanadianCash') then 1 else If ([Currencies].[CurrencyType]='ctMiscellaneous') then 2 else If ([Currencies].[CurrencyType]='ctTokens') then 3 else If ([Currencies].[Currency
                 |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Openers].[OpenerGUID]))
                      |--Filter(WHERE:((([Currencies].[IsActive]<>0 AND [Currencies].[OnOpener]<>0) AND ((((((([Currencies].[CurrencyType]='ctUSCoin' OR [Currencies].[CurrencyType]='ctMiscellaneousUS') OR [Currencies].[CurrencyType]='ctUSCash') OR [Currenc
                      |    |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Currencies].[CurrencyGUID], [Openers].[OpenerGUID]) WITH PREFETCH)
                      |         |--Filter(WHERE:([Openers].[SessionGUID]=[@SessionGUID]))
                      |         |    |--Concatenation
                      |         |         |--Nested Loops(Left Outer Join)
                      |         |         |    |--Table Spool
                      |         |         |    |    |--Hash Match(Inner Join, HASH:([Windows].[WindowGUID])=([Openers].[WindowGUID]), RESIDUAL:([Windows].[WindowGUID]=[Openers].[WindowGUID]))
                      |         |         |    |         |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Windows].[IX_Windows_CageGUID]))
                      |         |         |    |         |--Table Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Openers]))
                      |         |         |    |--Table Spool
                      |         |         |         |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                      |         |         |--Compute Scalar(DEFINE:([Openers].[OpenerGUID]=NULL, [Openers].[SessionGUID]=NULL, [Windows].[UseChipDenominations]=NULL))
                      |         |              |--Nested Loops(Left Anti Semi Join)
                      |         |                   |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                      |         |                   |--Row Count Spool
                      |         |                        |--Table Spool
                      |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID] AND [OpenerDetails].[CurrencyGUID]=[Cu
                      |--Hash Match(Cache, HASH:([Openers].[OpenerGUID]), RESIDUAL:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]))
                           |--Stream Aggregate(DEFINE:([Expr1006]=SUM([partialagg1034]), [Expr1007]=SUM([partialagg1035]), [Expr1008]=SUM([partialagg1036]), [Expr1009]=SUM([partialagg1037]), [Expr1010]=SUM([partialagg1038]), [Expr1011]=SUM([partialagg1039]
                                |--Nested Loops(Inner Join)
                                     |--Stream Aggregate(DEFINE:([partialagg1034]=SUM(If (((([Currencies].[CurrencyType]='ctMiscellaneous' OR [Currencies].[CurrencyType]='ctTokens') OR [Currencies].[CurrencyType]='ctChips') OR [Currencies].[CurrencyType]='
                                     |    |--Nested Loops(Inner Join, OUTER REFERENCES:([OpenerDetails].[CurrencyGUID]) WITH PREFETCH)
                                     |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                     |         |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[PK_Currencies_CurrencyGUID]), SEEK:([Currencies].[CurrencyGUID]=[OpenerDetails].[CurrencyGUID]) ORDERED FORWARD)
                                     |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_OneOpenerPerSession]), SEEK:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)

खराब-एक उत्सुक स्पूलिंग 6 मिलियन पंक्तियाँ हैं; अन्य एक नहीं है।

नोट: यह एक प्रश्न के बारे में सवाल नहीं है। मेरे पास एक क्वेरी है जो तेज बिजली चलाता है। मैं सिर्फ SQL सर्वर को संग्रहीत कार्यविधि से तेज़ चलाना चाहता हूँ।


मैं हर बार नोटिस करता हूं कि आप एक पैरामीटर लेते हैं और इसे दूसरे को फिर से असाइन करते हैं और फिर एक क्वेरी में इसका उपयोग करते हैं बाद में ऐसा हो सकता है और जैसा कि उत्तर पता चलता है कि @ "someparamname" के लिए ऑप्टिमाइज़ काम कर सकता है।
JustDave

जवाबों:


404

मुझे मूल पोस्टर के समान ही समस्या थी लेकिन उद्धृत उत्तर ने मेरे लिए समस्या का समाधान नहीं किया। क्वेरी अभी भी संग्रहीत प्रक्रिया से बहुत धीमी गति से चलती है।

मुझे यहां एक और जवाब मिला "पैरामीटर सूंघना " , धन्यवाद ओम्निबज़। आपके संग्रहीत कार्यविधि प्रश्नों में "स्थानीय चर" का उपयोग करने के लिए उबालता है, लेकिन अधिक समझ के लिए मूल पढ़ें, यह एक शानदार लेखन है। जैसे

धीमा तरीका:

CREATE PROCEDURE GetOrderForCustomers(@CustID varchar(20))
AS
BEGIN
    SELECT * 
    FROM orders
    WHERE customerid = @CustID
END

तेज़ तरीका:

CREATE PROCEDURE GetOrderForCustomersWithoutPS(@CustID varchar(20))
AS
BEGIN
    DECLARE @LocCustID varchar(20)
    SET @LocCustID = @CustID

    SELECT * 
    FROM orders
    WHERE customerid = @LocCustID
END

आशा है कि यह किसी और की मदद करता है, ऐसा करने से मेरा निष्पादन समय 5+ मिनट से घटकर लगभग 6-7 सेकंड हो गया।


23
+1 लेकिन, यह बहुत अजीब है, और बहुत सारे प्रश्नों को उठना चाहिए जैसे कि हमें सभी प्रक्रियाओं के लिए यह करना चाहिए और यदि नहीं, तो यह कब करना है?
gotqn

31
क्या मैं अकेला हूँ जो इस व्यवहार से चकित हूँ ?? पैरामीटर सूँघने से रोकने के लिए स्थानीय चरों को घोषित करने की आवश्यकता है ?? क्या SQL सर्वर को पहले स्थान पर होने से रोकने के लिए पर्याप्त स्मार्ट नहीं होना चाहिए? यह सिर्फ Microsoft के शॉर्टसाइट डिज़ाइन IMHO द्वारा अनावश्यक कोड ब्लोट का कारण बनता है।
l46kok

4
15 मिनट -> 8 सेकंड! जीवन रक्षक
टोनी ब्रिक्स

3
@ बेनेटडिल WITH RECOMPILEने मेरे लिए, केवल स्थानीय मापदंडों का फर्क नहीं किया।
mrogers

8
यह अब क्वेरी संकेत का उपयोग करके प्राप्त किया जा सकता है - विकल्प (OPTIMIZE FOR (@varA UNKNOWN, @varB UNKNOWN)
डेव

131

मुझे यह समस्या मिली, यहाँ संग्रहीत प्रक्रिया के धीमे और तेज़ संस्करणों की स्क्रिप्ट है:

dbo.ViewOpener__RenamedForCruachan__Slow.PRC

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS OFF 
GO

CREATE PROCEDURE dbo.ViewOpener_RenamedForCruachan_Slow
    @SessionGUID uniqueidentifier
AS

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank
GO

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

dbo.ViewOpener__RenamedForCruachan__Fast.PRC

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

CREATE PROCEDURE dbo.ViewOpener_RenamedForCruachan_Fast
    @SessionGUID uniqueidentifier 
AS

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank
GO

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

यदि आपने अंतर नहीं पाया, तो मैं आपको दोष नहीं देता। अंतर संग्रहीत कार्यविधि में बिल्कुल नहीं है। वह अंतर जो तेज 0.5 लागत क्वेरी को एक में बदल देता है जो 6 मिलियन पंक्तियों का एक स्पूल करता है:

धीरे: SET ANSI_NULLS OFF

तेज: SET ANSI_NULLS ON


यह उत्तर भी समझ में आता है, क्योंकि दृश्य में एक क्लॉज है जो कहता है:

(table.column IS NOT NULL)

तो कुछ NULLएस शामिल है।


क्वेरी विश्लेषक के पास लौटने और दौड़ने से स्पष्टीकरण आगे साबित होता है

SET ANSI_NULLS OFF

DECLARE @SessionGUID uniqueidentifier
SET @SessionGUID = 'BCBA333C-B6A1-4155-9833-C495F22EA908'

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

और क्वेरी धीमी है।


तो समस्या यह नहीं है क्योंकि क्वेरी को संग्रहीत कार्यविधि से चलाया जा रहा है। समस्या यह है कि एंटरप्राइज़ मैनेजर का कनेक्शन डिफ़ॉल्ट विकल्प है ANSI_NULLS off, बजाय इसके ANSI_NULLS onकि क्यूए डिफ़ॉल्ट है।

Microsoft KB296769 में इस तथ्य को स्वीकार करता है (BUG: लिंक किए गए सर्वर ऑब्जेक्ट युक्त संग्रहीत कार्यविधियाँ बनाने के लिए SQL एंटरप्राइज़ प्रबंधक का उपयोग नहीं कर सकता)। वर्कअराउंड ANSI_NULLSमें संग्रहीत कार्यविधि संवाद में विकल्प शामिल है :

Set ANSI_NULLS ON
Go
Create Proc spXXXX as
....

2
मुझे अभी भी समझ में नहीं आया कि कैसे मोड़ ANSI_NULLS ONइस तरह के एक विशाल प्रदर्शन अंतर बनाता है।
जस्टिन हेलगर्सन

2
@ Ek0nomik क्योंकि JOINजब दृश्य के अंदर खंडों का अलग अर्थ होता है ANSI_NULLS OFF। अचानक पंक्तियाँ मेल खाती हैं, जिससे ऑप्टिमाइज़र क्वेरी को पूरी तरह से अलग तरीके से चलाता है। कल्पना करें कि सभी पंक्तियों के 99.9% को खत्म करने के बजाय, वे अचानक वापस आ जाते हैं।
इयान बॉयड

2
नोट: ANSI_NULLS OFFपदावनत किया जाता है और एक बुरा अभ्यास माना जाता है
जीन

2
लिंक "SQL सर्वर के भविष्य के संस्करण में, ANSI_NULLS हमेशा चालू रहेगा और बंद करने का विकल्प स्पष्ट रूप से सेट करने वाला कोई भी एप्लिकेशन एक त्रुटि उत्पन्न करेगा। नए विकास कार्यों में इस सुविधा का उपयोग करने से बचें, और वर्तमान में इस सुविधा का उपयोग करने वाले अनुप्रयोगों को संशोधित करने की योजना बनाएं। "
11:24 बजे sotn

मेरे मामले में मदद नहीं की।
st_stefanov

19

अपने डेटाबेस के लिए यह करें। मेरे पास एक ही मुद्दा है - यह एक डेटाबेस में ठीक काम करता है, लेकिन जब मैं एसएसआईएस आयात (सामान्य पुनर्स्थापना नहीं) का उपयोग करके इस डेटाबेस को कॉपी करता हूं, तो यह समस्या मेरी अधिकांश संग्रहीत प्रक्रियाओं के लिए होती है। इसलिए कुछ और गुगली करने के बाद, मुझे पीनल डेव का ब्लॉग मिला (जो कि btw, मैंने उनकी अधिकांश पोस्ट का सामना किया और मुझे बहुत मदद की इसलिए धन्यवाद पिनाल डेव)

मैं अपने डेटाबेस पर नीचे की क्वेरी निष्पादित करता हूं और इसने मेरी समस्या को ठीक किया:

EXEC sp_MSforeachtable @command1="print '?' DBCC DBREINDEX ('?', ' ', 80)"
GO
EXEC sp_updatestats
GO 

उम्मीद है की यह मदद करेगा। बस दूसरों की मदद से गुजरने से मेरी मदद की।


2
भविष्य के पाठकों के लिए बस एक FYI: DBCC REINDEXको हटा दिया गया है, इसलिए आपको विकल्पों की तलाश करनी चाहिए।
ग्वे

1
फिक्स्ड मेरा मुद्दा, धन्यवाद (1m20s 2s नीचे!)। पुन:, DBCC DBREINDEXMS का कहना है: "यह सुविधा Microsoft SQL सर्वर के भविष्य के संस्करण में हटा दी जाएगी। नए विकास कार्यों में इस सुविधा का उपयोग न करें, और उन अनुप्रयोगों को संशोधित करें जो वर्तमान में इस सुविधा का जल्द से जल्द उपयोग करते हैं। इसके बजाय ALTER INDEX का उपयोग करें।"
AjV Jsy

पता नहीं अगर यह सबसे अच्छा जवाब है, लेकिन मेरे मामले में sp_updatestats यह सब लिया है, तो +1
टोड

..हाँ, और यह मत भूलो कि आपके उत्पादन सर्वर पर इसे निष्पादित करने से पहले अनुक्रमणिका अनुक्रमित समय और स्थान ले सकता है, सुनिश्चित करें कि आप संभावित मंदी को बर्दाश्त कर सकते हैं। मैं आपको (ONLINE = ON) के साथ REORGANIZE या REBUILD देखने का सुझाव दूंगा
मिलन

14

मैं एक ही मुद्दे का सामना कर रहा था और यह पोस्ट मेरे लिए बहुत उपयोगी थी, लेकिन किसी भी पोस्ट ने मेरे विशिष्ट मुद्दे को हल नहीं किया। मैं उस समाधान को पोस्ट करना चाहता था जो मेरे लिए काम करता है इस उम्मीद में कि यह किसी और की मदद कर सकता है।

https://stackoverflow.com/a/24016676/814299

अपनी क्वेरी के अंत में, विकल्प (OPTIMIZE FOR (@now UNKNOWN)) जोड़ें


4

इस बार आपको अपनी समस्या मिल गई। यदि अगली बार आप कम भाग्यशाली हैं और इसका पता नहीं लगा सकते हैं, तो आप प्लान फ्रीजिंग का उपयोग कर सकते हैं और गलत निष्पादन योजना के बारे में चिंता करना बंद कर सकते हैं ।


उस ब्लॉग प्रविष्टि के अनुसार, प्लान फ्रीजिंग केवल MS SQL 2005 और उसके बाद के लिए है, इसलिए यह OP की मदद नहीं करेगा।
कॉक्सी जूल

समस्या यह थी कि यह गलत क्वेरी प्लान का उपयोग कर रहा था। मैं इसे गलत करने के लिए फ्रीज नहीं करना चाहता।
इयान बॉयड

4

मैं इस समस्या का सामना कर रहा था। मेरी क्वेरी कुछ इस तरह दिखी:

select a, b, c from sometable where date > '20140101'

मेरी संग्रहीत प्रक्रिया इस तरह परिभाषित की गई थी:

create procedure my_procedure (@dtFrom date)
as
select a, b, c from sometable where date > @dtFrom

मैंने डेटाटाइप को डेटाइम और वॉइला में बदल दिया है! 30 मिनट से 1 मिनट तक चला गया!

create procedure my_procedure (@dtFrom datetime)
as
select a, b, c from sometable where date > @dtFrom

2
बहुत बहुत धन्यवाद, यह मेरा दिन बच गया! यहां बताया गया है कि मुझे डेटाइम क्षेत्र का केवल दिनांक भाग कैसे मिलता है: DATEADD (dd, 0, DatedIFF (dd, 0, table.field))
जुलिएन बी।

1
मेरी समस्या का समाधान। मेरे पास कॉलम varchar (20) था और मेरा पैरामीटर nvarchar (50) था, एक बार जब मैंने पैरामीटर को कॉलम प्रकार के समान बनाया - कोई और देरी नहीं।
st_stefanov

3

क्या आपने Report_Opener टेबल पर आँकड़ों और / या अनुक्रमितों के पुनर्निर्माण की कोशिश की है। यदि डेटाबेस को पहले निष्क्रिय किया गया था, तो आँकड़े अभी भी डेटा दिखाते हैं, तो सपा की सभी पुनरावृत्ति कुछ भी लायक नहीं होगी।

प्रारंभिक क्वेरी स्वयं काम करती है क्योंकि आशावादी देख सकता है कि पैरामीटर कभी भी अशक्त नहीं होगा। एसपी के मामले में आशावादी यह सुनिश्चित नहीं कर सकता है कि पैरामीटर कभी भी अशक्त नहीं होगा।


क्या एक संग्रहीत प्रक्रिया घोषणा में इंगित करने का एक तरीका है कि मैं पैरामीटर शून्य नहीं हो सकता है? और क्या यह ऐसा कुछ नहीं है जो sp_executesql द्वारा तय किया जाएगा?
इयान बोयड

एक शब्द में, 2000 में नहीं। 2005 में एक क्वेरी संकेत जोड़ा गया जहां आप एक पैरामीटर के लिए एक उदाहरण मूल्य प्रदान कर सकते हैं, ऑप्टिमाइज़र इस तरह से अनुकूलन करेगा जैसे कि यह जानता था कि पैरामीटर हमेशा उपयोग किया जाता था। यह कहते हुए कि मैंने आम तौर पर इस तरह की चीजों को एक सांख्यिकी समस्या के रूप में पाया है।
एंथनीवजोन

यदि यह एक आँकड़ों की समस्या है, तो वे इसे QA से ठीक काम करते हैं जब मैं इसे ad-hoc, sp_executesql, exec () चलाता हूं। और वे सभी तब खराब क्यों चलाते हैं जब एक संग्रहीत प्रक्रिया में तदर्थ वर्ग, sp_executesql, निष्पादन () शामिल हैं?
इयान बॉयड

1

हालांकि मैं आमतौर पर इसके खिलाफ हूं (हालांकि इस मामले में ऐसा लगता है कि आपके पास वास्तविक कारण है), क्या आपने क्वेरी के एसपी संस्करण पर कोई क्वेरी संकेत प्रदान करने की कोशिश की है? यदि SQL सर्वर उन दो उदाहरणों में एक अलग निष्पादन योजना तैयार कर रहा है, तो क्या आप यह बताने के लिए संकेत का उपयोग कर सकते हैं कि किस सूचकांक का उपयोग करना है, ताकि योजना पहले से मेल खाए?

कुछ उदाहरणों के लिए, आप यहां जा सकते हैं

संपादित करें: यदि आप अपनी क्वेरी योजना यहां पोस्ट कर सकते हैं, तो शायद हम उन योजनाओं के बीच कुछ अंतर की पहचान कर सकते हैं जो बता रहे हैं।

सेकंड: SQL-2000 विशिष्ट होने के लिए लिंक अद्यतन किया गया। आपको एक तरीके से नीचे स्क्रॉल करना होगा, लेकिन एक दूसरा शीर्षक "टेबल संकेत" है जो आप देख रहे हैं।

तृतीय: "बैड" क्वेरी "ओपनर्स" टेबल पर [IX_Openers_SessionGUID] को अनदेखा करती हुई प्रतीत होती है - किसी इंडेक्स के संकेत को जोड़ने का कोई भी मौका इसे उस सूचकांक का उपयोग करने के लिए बाध्य करने से चीजों को बदल देगा?


उस संदर्भ में सबसे उपयोगी क्वेरी संकेत SQL 2000 पर उपलब्ध नहीं हैं जो कि यहां प्रश्न में संस्करण है।
एंथनीवजोन

इसके अतिरिक्त, किन संकेतों की आवश्यकता है? एसक्यूएल सर्वर यह पता लगाने में सक्षम है कि जब मैं इसे एड-हॉक करता हूं तो यह कोई समस्या नहीं है।
इयान बोयड

ज़रूर, और यह हमेशा मेरा अनुभव भी रहा है। हालांकि, इस मामले में, वह कह रहा है कि यह पूरी तरह से अलग निष्पादन योजना के साथ आ रहा है। हो सकता है कि एक ऐसा सूचकांक है जिसका उपयोग तदर्थ में किया जाता है, लेकिन किसी कारण से खरीद में इसे अनदेखा किया जा रहा है। वह SQL सर्वर को "INDEX" संकेत के साथ सूचकांक का उपयोग करने के लिए मजबूर कर सकता है।
स्क्लर्यान

1

यह संभवत: संभावना नहीं है, लेकिन यह देखते हुए कि आपका मनाया गया व्यवहार असामान्य है, इसे जांचने की आवश्यकता है और किसी और ने इसका उल्लेख नहीं किया है।

क्या आप पूरी तरह से सुनिश्चित हैं कि सभी ऑब्जेक्ट्स dbo के स्वामित्व में हैं और आपके पास स्वयं या किसी अन्य उपयोगकर्ता के रूप में अच्छी तरह से मौजूद एक दुष्ट प्रति नहीं है?

बस कभी-कभी जब मैंने अजीब व्यवहार देखा है, क्योंकि यह वास्तव में एक वस्तु की दो प्रतियां थी और जो आपको मिलती है वह इस बात पर निर्भर करती है कि क्या निर्दिष्ट है और आप किसके रूप में लॉग ऑन हैं। उदाहरण के लिए एक ही नाम या प्रक्रिया की दो प्रतियां एक ही नाम के साथ पूरी तरह से संभव है, लेकिन अलग-अलग मालिकों के स्वामित्व में है - एक ऐसी स्थिति जो उत्पन्न हो सकती है जहां आप डेटाबेस पर एक डीबीओ के रूप में लॉग इन नहीं होते हैं और ऑब्जेक्ट स्वामी के रूप में डीबीओ निर्दिष्ट करना भूल जाते हैं जब आप वस्तु बनाते हैं।

ध्यान दें कि पाठ में आप मालिक को निर्दिष्ट किए बिना कुछ चीजें चला रहे हैं, जैसे

sp_recompile ViewOpener

उदाहरण के लिए अगर वहाँ देखने की दो प्रतियाँ मौजूद हैं जो dbo और [कुछ अन्य उपयोगकर्ता] के पास मौजूद हैं, तो आप जिनको निर्दिष्ट नहीं करते हैं, वे वास्तव में फिर से संगठित होते हैं। Report_Opener के दृश्य के साथ Ditto - अगर वहाँ जहाँ दो प्रतियाँ (और वे विनिर्देश या निष्पादन योजना में भिन्न हो सकती हैं) तो क्या उपयोग किया जाता है, यह परिस्थितियों पर निर्भर करता है - और जैसा कि आप मालिक को निर्दिष्ट नहीं करते हैं यह पूरी तरह से संभव है कि आपकी एडहॉक क्वेरी एक और एक का उपयोग कर सकती है संकलित प्रक्रिया दूसरे का उपयोग कर सकती है।

जैसा कि मैं कहता हूं, यह संभव नहीं है, लेकिन यह संभव है और इसकी जांच होनी चाहिए क्योंकि आपके मुद्दे हो सकते हैं कि आप बस गलत जगह पर बग की तलाश कर रहे हैं।


1

यह मूर्खतापूर्ण लग सकता है और SessionGUID नाम से स्पष्ट प्रतीत होता है, लेकिन क्या Report_Opener पर स्तंभ एक अद्वितीय पहचानकर्ता है? यदि नहीं, तो आप इसे सही प्रकार में डालने का प्रयास कर सकते हैं और इसे एक शॉट दे सकते हैं या अपने चर को सही प्रकार से घोषित कर सकते हैं।

स्पोक के हिस्से के रूप में बनाई गई योजना अनायास ही काम कर सकती है और एक बड़ी मेज पर एक आंतरिक कास्ट कर सकती है।


यह नहीं। लेकिन मैंने प्रदर्शन समस्याओं को एक ऐसे खंड के साथ देखा है जहां varcharएक nvarcharमान (उदाहरण WHERE CustomerName = N'zrendall') के साथ एक स्तंभ की तुलना की जा रही थी । SQL सर्वर को nvarcharतुलना करने से पहले प्रत्येक स्तंभ मान को परिवर्तित करना था ।
इयान बॉयड

0

मुझे एक और विचार आया है। यदि आप इस तालिका-आधारित फ़ंक्शन का निर्माण करते हैं:

CREATE FUNCTION tbfSelectFromView
(   
    -- Add the parameters for the function here
    @SessionGUID UNIQUEIDENTIFIER
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT *
    FROM Report_Opener
    WHERE SessionGUID = @SessionGUID
    ORDER BY CurrencyTypeOrder, Rank
)
GO

और फिर निम्न कथन का उपयोग करके इसे चुना गया (यहां तक ​​कि इसे अपने एसपी में डालकर):

SELECT *
FROM tbfSelectFromView(@SessionGUID)

ऐसा लगता है कि क्या हो रहा है (जो कि हर कोई पहले ही टिप्पणी कर चुका है) यह है कि SQL सर्वर सिर्फ एक धारणा बनाता है कि कहीं गलत है, और शायद यह धारणा को सही करने के लिए मजबूर करेगा। मुझे अतिरिक्त कदम जोड़ने से नफरत है, लेकिन मुझे यकीन नहीं है कि इसके कारण और क्या हो सकते हैं।


0

- यहाँ समाधान है:

create procedure GetOrderForCustomers(@CustID varchar(20))

as

begin

select * from orders

where customerid = ISNULL(@CustID, '')

end

-- बस

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.