Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

क्या स्थानीय चरों के लिए संग्रहीत कार्यविधि इनपुट पैरामीटर निर्दिष्ट करने से क्वेरी को अनुकूलित करने में मदद मिलती है?

मैं पैरामीटर सूँघने के पूर्ण विवरण की कोशिश और व्याख्या नहीं करूँगा, लेकिन संक्षेप में, नहीं, यह हमेशा नहीं है मदद (और यह बाधा डाल सकती है)।

एक प्राथमिक कुंजी और अनुक्रमित दिनांक कॉलम (ए) के साथ एक तालिका (टी) की कल्पना करें, तालिका में 1,000 पंक्तियां हैं, 400 में ए का समान मूल्य है (आज 20130122 कहें), शेष 600 पंक्तियां अगले 600 दिन हैं , इसलिए प्रति दिनांक केवल 1 रिकॉर्ड।

यह प्रश्न:

SELECT *
FROM T
WHERE A = '20130122';

इसके लिए एक अलग निष्पादन योजना तैयार करेगा:

SELECT *
FROM T
WHERE A = '20130123';

चूंकि आंकड़े इंगित करेंगे कि 1,000 पंक्तियों में से पहली 400 के लिए लौटा दी जाएगी, ऑप्टिमाइज़र को यह पहचानना चाहिए कि एक बुकमार्क लुकअप की तुलना में एक टेबल स्कैन अधिक कुशल होगा, जबकि दूसरा केवल 1 पंक्तियां देगा, इसलिए एक बुकमार्क लुकअप बहुत अधिक होगा अधिक कुशल।

अब, अपने प्रश्न पर वापस जाएं, यदि हमने इसे एक प्रक्रिया बना दिया है:

CREATE PROCEDURE dbo.GetFromT @Param DATE
AS
    SELECT *
    FROM T
    WHERE A = @Param

फिर दौड़ें

EXECUTE dbo.GetFromT '20130122'; --400 rows

तालिका स्कैन के साथ क्वेरी योजना का उपयोग किया जाएगा, यदि आप इसे पहली बार चलाते हैं तो आप पैरामीटर के रूप में '20130123' का उपयोग करते हैं, यह बुकमार्क लुकअप योजना को संग्रहीत करेगा। जब तक प्रक्रिया को फिर से संकलित नहीं किया जाता है, तब तक योजना वही रहेगी। कुछ इस तरह करना:

CREATE PROCEDURE dbo.GetFromT @Param VARCHAR(5)
AS
    DECLARE @Param2 VARCHAR(5) = @Param;
    SELECT *
    FROM T
    WHERE A = @Param2

फिर इसे चलाया जाता है:

EXECUTE dbo.GetFromT '20130122';

जबकि प्रक्रिया एक बार में संकलित की जाती है, यह ठीक से प्रवाहित नहीं होती है, इसलिए पहले संकलन में बनाई गई क्वेरी योजना को पता नहीं है कि @ परम 2 @ परम के समान हो जाएगा, इसलिए ऑप्टिमाइज़र (कितनी पंक्तियों के बारे में कोई जानकारी नहीं है) उम्मीद है) मान लेंगे कि 300 वापस कर दिए जाएंगे (30%), जैसे कि एक टेबल स्कैन को एक बुकमार्क लुकअप से अधिक कुशल माना जाएगा। यदि आप पैरामीटर के रूप में '20130123' के साथ एक ही प्रक्रिया चलाते हैं तो यह वही योजना उत्पन्न करेगा (चाहे वह किस पैरामीटर के साथ पहली बार लागू किया गया था) क्योंकि आंकड़ों का उपयोग एक अज्ञात मान के लिए नहीं किया जा सकता है। इसलिए '20130122' के लिए इस प्रक्रिया को चलाना अधिक कुशल होगा, लेकिन अन्य सभी मूल्यों के लिए स्थानीय मापदंडों के बिना कम कुशल होगा (यह मानते हुए कि स्थानीय मापदंडों के बिना प्रक्रिया को पहले '20130122' के अलावा कुछ भी लागू किया गया था)

कुछ प्रश्न प्रदर्शित करने के लिए ताकि आप अपने लिए निष्पादन योजनाएं देख सकें

स्कीमा और नमूना डेटा बनाएं

CREATE TABLE T (ID INT IDENTITY(1, 1) PRIMARY KEY, A DATE NOT NULL, B INT,C INT, D INT, E INT);

CREATE NONCLUSTERED INDEX IX_T ON T (A);

INSERT T (A, B, C, D, E)
SELECT  TOP 400 CAST('20130122' AS DATE), number, 2, 3, 4 
FROM    Master..spt_values 
WHERE   type = 'P'
UNION ALL
SELECT TOP 600 DATEADD(DAY, number, CAST('20130122' AS DATE)), number, 2, 3, 4 
FROM    Master..spt_values 
WHERE   Type = 'P';
GO
CREATE PROCEDURE dbo.GetFromT @Param DATE
AS
    SELECT *
    FROM T
    WHERE A = @Param
GO
CREATE PROCEDURE dbo.GetFromT2 @Param DATE
AS
    DECLARE @Param2 DATE = @Param;
    SELECT *
    FROM T
    WHERE A = @Param2
GO

कार्यविधियाँ चलाएँ (वास्तविक निष्पादन योजना दिखा रहा है):

EXECUTE GetFromT '20130122';
EXECUTE GetFromT '20130123';
EXECUTE GetFromT2 '20130122';
EXECUTE GetFromT2 '20130123';
GO
EXECUTE SP_RECOMPILE GetFromT;
EXECUTE SP_RECOMPILE GetFromT2;
GO
EXECUTE GetFromT '20130123';
EXECUTE GetFromT '20130122';
EXECUTE GetFromT2 '20130123';
EXECUTE GetFromT2 '20130122';

आप देखेंगे कि पहली बार GetFromT संकलित किया गया है यह एक टेबल स्कैन का उपयोग करता है, और पैरामीटर '20130122' के साथ चलने पर इसे बरकरार रखता है, GetFromT2 टेबल स्कैन का भी उपयोग करता है और '20130122' के लिए योजना को बरकरार रखता है।

प्रक्रियाओं को पुनर्संकलन के लिए सेट करने और फिर से चलाने के बाद (एक अलग क्रम में नोट करें), GetFromT एक बुकमार्क लूपअप का उपयोग करता है, और '20130122' के लिए योजना को बरकरार रखता है, जबकि पहले यह माना जाता था कि टेबल स्कैन एक अधिक उपयुक्त योजना है। GetFromT2 आदेश से अप्रभावित है और पुनर्अनुपालन से पहले की ही योजना है।

तो, संक्षेप में, यह आपके डेटा के वितरण पर निर्भर करता है, और आपकी अनुक्रमणिका, आपके पुन:संकलन की आवृत्ति, और थोड़ी सी किस्मत पर निर्भर करता है कि स्थानीय चर का उपयोग करने से कोई प्रक्रिया लाभान्वित होगी या नहीं। यह निश्चित रूप से हमेशा नहीं है मदद।

उम्मीद है कि मैंने स्थानीय मानकों, निष्पादन योजनाओं और संग्रहीत प्रक्रिया अनुपालन का उपयोग करने के प्रभाव पर कुछ प्रकाश डाला है। अगर मैं पूरी तरह से विफल हो गया हूं, या एक महत्वपूर्ण बिंदु चूक गया हूं तो यहां गहराई से स्पष्टीकरण मिल सकता है:

http://www.sommarskog.se/query-plan-mysteries.html ए>



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. nvarchar(अधिकतम) बनाम NText

  2. SQL सर्वर राउंड () फ़ंक्शन:इसके लिए क्या है और आपको इसकी परवाह क्यों करनी चाहिए?

  3. Ubuntu 18.04 पर Azure डेटा स्टूडियो स्थापित करें

  4. कॉलम के मान के आधार पर लगातार पंक्तियों को कैसे खोजें?

  5. एक nvarchar mssql क्षेत्र में यूनिकोड या utf-8 वर्ण सम्मिलित करने के लिए linux पर pyodbc का उपयोग करना