यह SQL सर्वर आंतरिक योजना कैशिंग श्रृंखला का भाग है। इस विषय पर कलेन की पहली पोस्ट अवश्य पढ़ें।
SQL सर्वर को लगभग 30 वर्षों से अधिक हो गया है, और मैं लगभग लंबे समय से SQL सर्वर के साथ काम कर रहा हूँ। मैंने इस अविश्वसनीय उत्पाद के वर्षों (और दशकों!) और संस्करणों में बहुत सारे बदलाव देखे हैं। इन पोस्ट में मैं आपके साथ साझा करूँगा कि मैं SQL सर्वर की कुछ विशेषताओं या पहलुओं को कैसे देखता हूँ, कभी-कभी थोड़े से ऐतिहासिक परिप्रेक्ष्य के साथ
मेरे पिछले लेख . में , मैंने SQL सर्वर डायग्नोस्टिक्स के बारे में बात की, जिसमें क्वेरी प्लान के पुन:उपयोग के लिए SQL सर्वर के पास विभिन्न विकल्प शामिल हैं। हमने तीन प्रकार की क्वेरी योजनाओं को देखा:तदर्थ, तैयार और प्रक्रिया। मैंने एक योजना के अनुचित पुन:उपयोग पर एक नज़र के साथ चर्चा समाप्त की, जो तब हो सकता है जब SQL सर्वर गलत परिस्थितियों में सूँघने वाले पैरामीटर को लागू करता है। यदि कोई योजना प्रारंभिक मान पर आधारित है जिसके कारण अनुकूलक उस मान के लिए उपयुक्त योजना बनाता है, और फिर उसी योजना का उपयोग भिन्न मान के लिए किया जाता है, तो योजना अब इष्टतम नहीं रह सकती है।
तो, पैरामीटर सूँघने में समस्या होने पर हम क्या कर सकते हैं? हम SQL सर्वर को एक नई योजना के साथ आने के लिए बाध्य कर सकते हैं। आमतौर पर, हम एक नई योजना के साथ आने की क्रिया को 'पुनः संकलन' कहते हैं, लेकिन इसे शायद 'पुन:अनुकूलन' कहा जाना चाहिए। हालांकि, ज्यादातर लोग 'रीकंपाइल' शब्द का इस्तेमाल करते हैं, इसलिए मैं यहां इसका इस्तेमाल करूंगा।
यदि पैरामीटर सूँघने का अनुचित उपयोग एक समस्या है, तो एक सरल उपाय यह है कि SQL सर्वर को एक नई योजना के साथ आने के लिए कहें। अलग-अलग बयानों के लिए, जैसे कि तैयार की गई योजनाओं के साथ, जिन्हें ऑटोपैरामीटर किया गया है, हम एक क्वेरी में RECOMPILE संकेत जोड़ सकते हैं। FORCED पैरामीटराइज़्ड (पिछले लेख में चर्चा की गई) का उपयोग करके, इस क्वेरी को पैरामीटराइज़ किया जाएगा।
SELECT * FROM dbo.newsales
WHERE SalesOrderID < @num;
अगर हम यह सुनिश्चित करना चाहते हैं कि हर बार जब हम इस क्वेरी को चलाते हैं तो हमें एक नई योजना मिलती है, संभावित रूप से @num के लिए काफी भिन्न मानों के साथ, हम दिखाए गए अनुसार RECOMPILE संकेत जोड़ सकते हैं:
SELECT * FROM dbo.newsales
WHERE SalesOrderID < @num
OPTION (RECOMPILE);
संग्रहीत कार्यविधियों के लिए, हमारे पास तीन विकल्प हैं। सबसे पहले, हम यह पता लगा सकते हैं कि RECOMPILE विकल्प के साथ प्रक्रिया को निष्पादित करके पुन:संकलन वास्तव में प्रदर्शन में मदद करेगा या नहीं:
EXEC get_sales_range 66666 WITH RECOMPILE;
यह विकल्प केवल इस एक निष्पादन के लिए एक नई योजना तैयार करने का कारण बनेगा। इसे सहेजा नहीं जाएगा और निश्चित रूप से पुन:उपयोग नहीं किया जाएगा। प्रक्रिया के लिए sp_cacheobjects (पिछली पोस्ट में वर्णित) में दिखाया गया usecount मान नहीं बढ़ेगा क्योंकि मूल योजना का पुन:उपयोग नहीं किया जा रहा है।
दूसरा, अगर हम पाते हैं कि RECOMPILE के साथ क्रियान्वित करने से मदद मिलती है, तो हम RECOMPILE विकल्प के साथ प्रक्रिया को फिर से बनाने पर विचार कर सकते हैं, इस स्थिति में यह कभी भी योजना का पुन:उपयोग नहीं करेगा और प्रक्रिया योजना कैश में बिल्कुल भी दिखाई नहीं देगी।
DROP PROC IF EXISTS get_sales_range;GO
CREATE PROC get_sales_range
@num int
WITH RECOMPILE
AS
SELECT * FROM dbo.newsales
WHERE SalesOrderID < @num;
GO
मेरी सरल छोटी प्रक्रिया के लिए, पूरी प्रक्रिया के लिए RECOMPILE विकल्प के साथ का उपयोग करना समझ में आ सकता है। लेकिन अगर प्रक्रिया अधिक जटिल है, तो पूरी प्रक्रिया को फिर से संकलित करने का कोई मतलब नहीं हो सकता है क्योंकि एक कथन समस्या पैदा कर रहा है। तो, तीसरा विकल्प प्रक्रिया के भीतर एक बयान के लिए RECOMPILE संकेत का उपयोग करना है, इसलिए यह इस तरह दिखता है:
DROP PROC IF EXISTS get_sales_range;
GO
CREATE PROC get_sales_range
@num int
AS
SELECT * FROM dbo.newsales
WHERE SalesOrderID < @num
OPTION (RECOMPILE);
GO
इन RECOMPILE विकल्पों में से किसी एक का उपयोग करने से SQL सर्वर आपके अनुरोध पर एक नई योजना के साथ आने के लिए बाध्य हो सकता है। अब, हम देखेंगे कि जब आप अनुरोध नहीं करते हैं तो आपका SQL सर्वर डायग्नोस्टिक्स एक नई योजना के साथ आता है, यानी किसी मौजूदा योजना का स्वचालित पुनर्संकलन कब होता है?
किसी योजना का स्वत:पुन:संकलन दो प्रकार की स्थितियों में होता है:
- सबसे पहले, यदि ऑप्टिमाइज़र यह निर्धारित करता है कि मौजूदा योजना अब सही नहीं है, आमतौर पर वस्तु परिभाषाओं में बदलाव के कारण, उसे एक नई योजना के साथ आने की आवश्यकता होगी। उदाहरण के लिए, यदि आपके पास टेबलए से चयन करने वाली क्वेरी के लिए एक योजना है, और फिर आप टेबलए में कई कॉलम छोड़ते हैं, या कॉलम के डेटाटाइप बदलते हैं, तो SQL सर्वर डीडीएल परिवर्तनों को प्रतिबिंबित करने वाली योजना के साथ आने के लिए क्वेरी को फिर से संकलित करेगा।ली>
- दूसरी स्थिति जिसमें स्वचालित पुन:संकलन होता है, जब SQL सर्वर यह निर्धारित करता है कि आंकड़ों में बदलाव के कारण योजना अब इष्टतम नहीं हो सकती है। ज्यादातर मामलों में, यदि पिछली बार योजना के संकलन के बाद से किसी भी कॉलम या इंडेक्स पर आंकड़े अपडेट किए गए हैं, तो इसे फिर से संकलित किया जाएगा। लेकिन यह एक और सवाल की ओर ले जाता है। आंकड़े कब अपडेट किए जाते हैं? प्रासंगिक कॉलम में पर्याप्त पंक्तियों में परिवर्तन होने पर आंकड़े स्वचालित रूप से अपडेट किए जा सकते हैं। कितने पर्याप्त हैं? हम इसके बारे में शीघ्र ही बात करते हैं।
डिफ़ॉल्ट रूप से, SQL सर्वर डेटाबेस विकल्प के कारण स्वचालित रूप से आँकड़ों को अद्यतन करेगा जो डिफ़ॉल्ट रूप से चालू है। लेकिन अगर आप एक डेटाबेस के मालिक हैं (या एक SQL 'sa', जो हर डेटाबेस में मालिक के रूप में दिखाई देता है), तो आप विकल्प बदल सकते हैं। विकल्पों में से एक को AUTO_UPDATE_STATISTICS और दूसरे को AUTO_UPDATE_STATISTICS_ASYNC कहा जाता है। विकल्प AUTO_UPDATE_STATISTICS tempdb डेटाबेस में चालू है, इसलिए प्रत्येक नए डेटाबेस को यह विकल्प प्राप्त होता है। जब यह विकल्प चालू होता है, और क्वेरी निष्पादन इंजन क्वेरी को संसाधित करते समय पर्याप्त संख्या में पंक्तियों में परिवर्तन का पता लगाता है, तो आंकड़े अपडेट होने पर निष्पादन रुक जाएगा और फिर क्वेरी को फिर से संकलित किया जाएगा। दूसरा विकल्प, AUTO_UPDATE_STATISTICS_ASYNC, संभावित रूप से क्वेरी निष्पादन समय पर कम प्रभाव डाल सकता है क्योंकि एक संभावित उप-इष्टतम योजना का उपयोग करने की कीमत पर निष्पादन रुकता नहीं है। दूसरे विकल्प के साथ, यदि निष्पादन इंजन आंकड़ों को अद्यतन करने की आवश्यकता का पता लगाता है, तो अद्यतन करने के लिए पृष्ठभूमि थ्रेड को निकाल दिया जाता है, और मुख्य थ्रेड मूल आंकड़ों और मूल योजना के साथ क्वेरी निष्पादित करना जारी रखता है। अगली क्वेरी जो प्रभावित तालिकाओं तक पहुँचती है और अद्यतन आँकड़े देखती है, क्वेरी को फिर से संकलित करेगी, लेकिन यह रुकेगी नहीं और निष्पादन के बीच में आँकड़ों का अद्यतन करेगी।
कुछ और स्थितियां हैं और साथ ही कुछ क्वेरी संकेत हैं जो नियंत्रित करते हैं कि योजनाओं को पुन:संकलित किया गया है या नहीं, इसलिए मैं आपको एक फ़्लोचार्ट दिखाऊंगा जो मैं आपके साथ एक फ़्लोचार्ट साझा करूंगा जिसे मैंने SQL सर्वर इंटर्नल पर अपनी प्रशिक्षण कक्षाओं के लिए बनाया था।पी>
तीर वह जगह है जहाँ SQL सर्वर आपके बैच को संसाधित करना शुरू करता है। यह पहले यह देखने के लिए जांच करता है कि कैश में आपके बैच के लिए पहले से कोई योजना है या नहीं, और यदि उत्तर नहीं है, तो दाईं ओर तीर का अनुसरण करता है और एक योजना संकलित करता है। योजना को कैश में रखा जाता है, और उसके बाद SQL सर्वर पुन:प्रारंभ होता है। हां, इस बार योजना कैश में होनी चाहिए, इसलिए यह नीचे की ओर तीर का अनुसरण करती है और पूछती है कि क्या कीप प्लान नामक एक संकेत का उपयोग किया गया है। यदि हाँ, तो SQL सर्वर तुरंत योजना को क्रियान्वित करना शुरू कर देता है और आगे कोई जाँच नहीं करता है।
अगला सवाल यह है कि क्या डीडीएल में कोई बदलाव किया गया है। यदि नहीं, तो यह कई अन्य स्थितियों के बारे में पूछता है जिनके बारे में मैं इस लेख में बात नहीं कर पाऊंगा। वास्तव में, मैं वास्तव में यहाँ हर विकल्प के माध्यम से कदम नहीं उठाने जा रहा हूँ। मैं इसे आप पर छोड़ता हूँ। लेकिन अगर आपके कोई प्रश्न या भ्रम हैं, तो बेझिझक उनसे यहां टिप्पणी अनुभाग में पूछें, या मुझे @sqlqueen पर ट्वीट करें। मैं प्रश्न को सबसे दाईं ओर इंगित करूंगा:क्या AUTO_STATS_ASYNC चालू है? यहाँ, आप देख सकते हैं कि यदि उत्तर हाँ है, तो दो क्रियाएँ होती हैं। एक शाखा सिर्फ मौजूदा योजना के साथ निष्पादन शुरू करती है, और दूसरी पृष्ठभूमि धागा है जो आंकड़ों को अद्यतन करता है लेकिन फिर कुछ और नहीं करता है। अगली क्वेरी "क्या नए आँकड़े उपलब्ध हैं" के बीच में निर्णय बॉक्स का सामना करेगी और इसका उत्तर हाँ में देना चाहिए, इसलिए क्वेरी को फिर से संकलित किया जाएगा।
केवल एक और चीज जिसके बारे में मैं बात करूंगा वह यह है कि "क्या कोई आँकड़े बासी हैं?" इसका मूल रूप से मतलब है कि आँकड़े पुराने हैं क्योंकि बहुत सारे बदलाव किए गए हैं। तो अब हम बात कर सकते हैं कि कितने बहुत अधिक हैं।
हालाँकि, SQL सर्वर 2016 से पहले 500 से अधिक पंक्तियों वाली किसी भी तालिका के लिए बहुत छोटी तालिकाओं के लिए अलग-अलग मानों का उपयोग किया जाता है, लेकिन आंकड़ों को 'बासी' माना जाएगा, जब उस स्तंभ में परिवर्तनों की संख्या, जिन पर आँकड़े आधारित थे, 20 से अधिक हो गए। तालिका में पंक्तियों की संख्या का%। तो, 1000 पंक्तियों की तालिका के लिए, इसका मतलब 200 प्रविष्टियां, 200 अपडेट या 200 हटाना हो सकता है। यह 200 पंक्तियों में परिवर्तन हो सकता है, या 5 पंक्तियों में से प्रत्येक को 40 बार अपडेट किया जा सकता है। SQL सर्वर हमें एक फ़ंक्शन भी देता है जो रिपोर्ट करता है कि कितने बदलाव किए गए हैं। आपको उन आँकड़ों के लिए stats_id संख्या देखने की आवश्यकता होगी, जिनमें आप रुचि रखते हैं, जो कि index_id होगा यदि आँकड़े किसी अनुक्रमणिका से संबंधित हैं। Stats_id को sys.stats नामक दृश्य में पाया जा सकता है। मेरी समाचार-विक्रय तालिका में, मैं इस क्वेरी का उपयोग यह पता लगाने के लिए करता हूं कि SubTotal कॉलम पर इंडेक्स के लिए stats_id 3 है।
SELECT name, stats_id FROM sys.stats
WHERE object_id = object_id('newsales');
तब मैं उस मान का उपयोग परिवर्तनों की संख्या को देखने के लिए कर सकता हूं। मुझे पहले कुछ पंक्तियों को अपडेट करने दें:
UPDATE newsales
(1541 पंक्तियां प्रभावित)
SET SubTotal = SubTotal * 0.9
WHERE SalesOrderID < 45200
SELECT * FROM sys.dm_db_stats_properties(object_id('newsales'), 3);
वास्तव में, 20% एक बड़ी संख्या है। और कई तालिकाओं के लिए, क्वेरीज़ को अद्यतन आँकड़ों से लाभ हो सकता है, जिनमें 20% से कम पंक्तियाँ अपडेट की गई हैं। 2008R2 SP1 से शुरू होकर, SQL सर्वर में एक ट्रेसफ्लैग शामिल था जिसका उपयोग आप पंक्तियों की संख्या को स्लाइडिंग स्केल के रूप में बदलने के लिए कर सकते हैं, जैसा कि निम्न ग्राफ़ में दिखाया गया है:
SQL सर्वर 2016 में शुरू, स्लाइडिंग स्केल के साथ यह नया एल्गोरिथम डिफ़ॉल्ट रूप से उपयोग किया जाता है, जब तक कि आप संगतता स्तर 130 या उच्चतर में हों।
क्वेरी योजनाओं के अधिकांश स्वचालित पुनर्संकलन आँकड़ों में परिवर्तन के कारण होते हैं। लेकिन जैसा कि मैंने ऊपर उल्लेख किया है, यह एक पुन:संकलन का एकमात्र कारण नहीं है। लेकिन चूंकि यह सबसे आम है, इसलिए यह जानना बहुत उपयोगी हो सकता है कि आंकड़े कब और कैसे अपडेट किए जाते हैं और सुनिश्चित करें कि आपकी महत्वपूर्ण तालिकाओं के आंकड़े अक्सर अपडेट किए जाते हैं ताकि यह सुनिश्चित हो सके कि आपको सर्वोत्तम योजनाएं मिलती हैं!
समस्याओं को शीघ्रता से हल करने के लिए SQL सर्वर डायग्नोस्टिक्स करने के लिए स्वचालित रूप से प्रदर्शन डेटा का विश्लेषण करें और उन सर्वरों की पहचान करें जहां प्रदर्शन में गिरावट आई है। आज ही स्पॉटलाइट क्लाउड का उपयोग शुरू करें: