अपनी पिछली पोस्ट में, मैंने प्रश्नों को ट्यूनिंग करते समय उस प्रक्रिया की रूपरेखा तैयार करना शुरू कर दिया था - विशेष रूप से जब मुझे पता चलता है कि मुझे एक नई अनुक्रमणिका जोड़ने, या किसी मौजूदा को संशोधित करने की आवश्यकता है। इस बिंदु तक हमने समस्याग्रस्त क्वेरी की पहचान की है, मुझे जिस इंडेक्स की आवश्यकता है, वर्तमान में टेबल पर कौन से इंडेक्स मौजूद हैं, और उन इंडेक्स का उपयोग किया जा रहा है या नहीं। एक बार हमारे पास वह डेटा हो जाने के बाद, हम प्रक्रिया के अगले चरणों पर आगे बढ़ सकते हैं।
चरण 5:इंडेक्स का क्या उपयोग करता है
यह देखने के अलावा कि किसी इंडेक्स का कितनी बार उपयोग किया जाता है (या नहीं), यह जानना फायदेमंद है कि कौन सी क्वेरी एक इंडेक्स का उपयोग करें, खासकर यदि मैं इसे किसी अन्य इंडेक्स के साथ मर्ज करना चाहता हूं। सौभाग्य से, जोनाथन केहैयस ने पहले ही यह पहचानने में मदद के लिए एक प्रश्न लिखा है कि कौन सी योजनाएँ एक विशिष्ट सूचकांक का उपयोग करती हैं। उनके संस्करण का उपयोग प्लान कैश के लिए किया जा सकता है - जानकारी की एकमात्र चुनौती क्षणिक है, इसलिए आप किसी विशेष इंडेक्स का उपयोग करने वाली प्रत्येक क्वेरी को कैप्चर नहीं कर सकते हैं। क्वेरी स्टोर इसमें मदद कर सकता है - मैंने क्वेरी स्टोर में योजनाओं से समान जानकारी प्राप्त करने के लिए उसकी क्वेरी को संशोधित किया है:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED DECLARE @IndexName AS NVARCHAR(128) = N'[IX_Sales_OrderLines_AllocatedStockItems]', @lb AS nchar(1) = N'[', @rb AS nchar(1) = N']'; -- Make sure the name passed is appropriately quoted IF (LEFT(@IndexName, 1) <> @lb AND RIGHT(@IndexName, 1) <> @rb) SET @IndexName = QUOTENAME(@IndexName); --Handle the case where the left or right was quoted manually but not the opposite side IF LEFT(@IndexName, 1) <> @lb SET @IndexName = @rb + @IndexName; IF RIGHT(@IndexName, 1) <> @rb SET @IndexName = @IndexName + @rb; ;WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan') SELECT stmt.value('(@StatementText)[1]', 'varchar(max)') AS SQL_Text, obj.value('(@Database)[1]', 'varchar(128)') AS DatabaseName, obj.value('(@Schema)[1]', 'varchar(128)') AS SchemaName, obj.value('(@Table)[1]', 'varchar(128)') AS TableName, obj.value('(@Index)[1]', 'varchar(128)') AS IndexName, obj.value('(@IndexKind)[1]', 'varchar(128)') AS IndexKind, query_plan FROM ( SELECT query_plan FROM ( SELECT TRY_CONVERT(XML, [qsp].[query_plan]) AS [query_plan] FROM sys.query_store_plan [qsp] ) tp ) AS tab (query_plan) CROSS APPLY query_plan.nodes('/ShowPlanXML/BatchSequence/Batch/Statements/StmtSimple') AS batch(stmt) CROSS APPLY stmt.nodes('.//IndexScan/Object[@Index=sql:variable("@IndexName")]') AS idx(obj) OPTION(MAXDOP 1, RECOMPILE);
यह ध्यान देने योग्य है कि यह एक और बिंदु है जहां मैं अपने आप को एक खरगोश के छेद में बहुत गहराई से पा सकता हूं, जो कि मेरे द्वारा समीक्षा की जा रही अनुक्रमणिका की संख्या और उनका उपयोग करने वाले प्रश्नों की संख्या पर निर्भर करता है। यदि संभव हो, तो मैं केवल क्या समझने के लिए निष्पादन गणना (क्वेरी स्टोर या प्लान कैश से) पर विचार करूंगा query एक अनुक्रमणिका का उपयोग करता है, लेकिन वह क्वेरी कितनी बार निष्पादित होती है। यहीं पर इंडेक्स ट्यूनिंग एक कला बन जाती है। मैं हास्यास्पद मात्रा में डेटा एकत्र कर सकता हूं ... लेकिन मेरे पास विश्लेषण के लिए अनंत समय नहीं है, इसलिए मुझे निर्णय लेना होगा कि मैं कितने प्रश्नों की समीक्षा करने जा रहा हूं।
चरण 6:परीक्षण
सबसे सरल रूप में, किसी इंडेक्स का परीक्षण करने का अर्थ है समस्याग्रस्त क्वेरी लेना और योजना और प्रदर्शन डेटा (अवधि, आईओ, सीपीयू, आदि) को कैप्चर करना, और फिर इंडेक्स बनाना, क्वेरी को फिर से चलाना और उसी जानकारी को कैप्चर करना। यदि प्रदर्शन में सुधार होता है, तो आप जाने के लिए अच्छे हैं!
यह शायद ही कभी इतना आसान होता है।
शुरू करने के लिए, मेरे पास अक्सर एक इंडेक्स की कम से कम दो भिन्नताएं होती हैं जिन्हें मैं परीक्षण करना चाहता हूं, कभी-कभी अधिक। मैं अपनी आधार रेखा से शुरू करता हूं, फिर मैं सभी इंडेक्स विविधताएं बनाता हूं, योजना कैश साफ़ करता हूं, और देखता हूं कि SQL सर्वर क्या चुनता है। फिर मैं प्रत्येक इंडेक्स को एक संकेत के साथ रोल करता हूं और प्रत्येक निष्पादन के लिए योजना और प्रदर्शन मीट्रिक को कैप्चर करता हूं। नोट:यह मानता है कि मेरे पास सभी इंडेक्स के लिए पर्याप्त डिस्क स्थान है ... यदि नहीं, तो मैं उन्हें एक समय में एक बना देता हूं, और परीक्षण करता हूं। अंत में, मैं संख्याओं की तुलना करता हूं। अगर मैं सिर्फ एक नई अनुक्रमणिका जोड़ रहा हूं, तो मैं लगभग पूरा कर चुका हूं। लेकिन अगर मैं किसी इंडेक्स को संशोधित कर रहा हूं या एक जोड़े को एक साथ मिला रहा हूं, तो यह जटिल हो सकता है।
एक आदर्श दुनिया में, यदि मैं किसी मौजूदा इंडेक्स को संशोधित करता हूं, तो मुझे सबसे अधिक बार-बार/महत्वपूर्ण प्रश्न मिलते हैं जो वर्तमान इंडेक्स का उपयोग करते हैं और उनकी योजनाएं और प्रदर्शन मीट्रिक प्राप्त करते हैं (यह क्वेरी स्टोर के साथ आसान है)। फिर मैं सूचकांक बदलता हूं, उन सभी प्रश्नों को फिर से चलाता हूं, और देखता हूं कि क्या मुझे योजना के आकार और/या प्रदर्शन में महत्वपूर्ण परिवर्तन मिलते हैं।
अगर मैं दो इंडेक्स को मर्ज करता हूं, तो मैं वही काम करता हूं, लेकिन उन सभी प्रश्नों के साथ जो इंडेक्स का उपयोग करते हैं, और फिर मर्ज किए गए इंडेक्स के साथ फिर से परीक्षण करते हैं।
यदि मैं एक तालिका के लिए कई अनुक्रमणिका जोड़/बदल/विलय कर रहा हूं, तो मुझे सभी प्रासंगिक प्रश्न और उनकी योजनाएं और मीट्रिक प्राप्त करने, अनुक्रमणिका बदलने, फिर सभी जानकारी प्राप्त करने और तुलना करने की आवश्यकता है। यह बहुत समय लेने वाला हो सकता है, यह इस बात पर निर्भर करता है कि वहां कितने अलग-अलग प्रश्न हैं। यह वह जगह है जहां यह एक कला रूप है और आपको यह निर्धारित करना होगा कि आपको वास्तव में कितने प्रश्नों का परीक्षण करने की आवश्यकता है। यह निष्पादन की आवृत्ति, क्वेरी महत्व/प्रासंगिकता, और मेरे पास उपलब्ध/आवंटित समय का एक कार्य है।
अंत में, यदि मैं किसी तालिका में एक अनुक्रमणिका जोड़ता हूं, और मैं किसी भी मौजूदा को नहीं हटाता हूं, तो मैंने INSERTs, DELETEs और संभावित अद्यतनों के लिए ओवरहेड जोड़ दिया है। प्रदर्शन परीक्षण यह परिवर्तन संभव है, लेकिन आपको परीक्षण वातावरण और लोड परीक्षण चलाने की क्षमता और अवधि, आईओ और सीपीयू से संबंधित परिवर्तन-पूर्व और बाद के मैट्रिक्स को कैप्चर करने की आवश्यकता है।
यह बहुत सारे दोस्त हैं, यही वजह है कि यह विडंबना है कि मैंने शुरू में यह कहने के बारे में सोचा था कि इंडेक्स ट्यूनिंग आसान थी। यह हमेशा आसान नहीं हो सकता है, लेकिन यह संभव है। यह परिश्रम और इस पर नज़र रखने की बात है।
चरण 7:कार्यान्वयन
नए इंडेक्स (सूचकांकों) की यथासंभव जांच करने के बाद, हम उत्पादन के लिए तैयार हैं। मैं स्वीकार करता हूं कि मैं सूचकांक परिवर्तनों को कम जोखिम के रूप में देखता हूं, विशेष रूप से नए। यदि यह कोई समस्या है, तो आप इसे तुरंत छोड़ सकते हैं, और मूल स्थिति में वापस आ सकते हैं। एक संशोधित/मर्ज/ड्रॉप परिदृश्य के साथ, आप सब कुछ स्क्रिप्टेड करना चाहते हैं, ताकि आप इंडेक्स को रीसेट करने के लिए आवश्यकतानुसार इंडेक्स को बदल सकें और फिर से बना सकें। मैं हमेशा इंडेक्स को छोड़ने के बजाय शुरुआत में अक्षम करने की सलाह देता हूं, क्योंकि तब आपको परिभाषा के बारे में चिंता करने की ज़रूरत नहीं है - अगर आपको इंडेक्स को वापस जोड़ने की ज़रूरत है तो आप इसे फिर से बना सकते हैं।
सारांश
अनुक्रमणिका जोड़ने और/या समेकित करने का आपका तरीका भिन्न हो सकता है! क्वेरी ट्यूनिंग की तरह, कोई सही प्रक्रिया नहीं है। इंडेक्स ट्यूनिंग के लिए नए किसी के लिए, यह उम्मीद है कि समीक्षा और महत्वपूर्ण विचारों के लिए वस्तुओं का एक स्टार्टर प्रदान करता है। कुछ मात्रा में ओवरहेड जोड़े बिना इंडेक्स जोड़ना असंभव है - और फिर यह वह जगह है जहां कला आती है:आपको यह निर्धारित करना होगा कि इंडेक्स का लाभ संशोधनों के लिए इसकी लागत से अधिक है या नहीं।
इंडेक्स ट्यूनिंग एक सतत, चलने वाली प्रक्रिया है - मुझे नहीं लगता कि आपने कभी किया है, क्योंकि कोड परिवर्तन, नई टेबल या कार्यक्षमता जोड़े जाते हैं, और टेबल में डेटा बदल जाता है। किम्बर्ली के दो पद हैं (https://www.sqlskills.com/blogs/kimberly/spring-cleaning-your-indexes-part-i/ और https://www.sqlskills.com/blogs/kimberly/spring-cleaning- your-indexes-part-ii/) जो आपकी अनुक्रमणिका को साफ करने के बारे में बात करते हैं - अब उतना ही अच्छा समय है जितना कि शुरू करने के लिए! और अंत में, जब भी कोई पूछता है, "एक टेबल के लिए कितने इंडेक्स होने चाहिए?" मैं कुछ इस तरह से उत्तर देता हूं, "जितना संभव हो उतने प्रश्नों को संतुष्ट करने के लिए आपको सबसे कम संख्या की आवश्यकता है।" कोई जादुई संख्या नहीं है - मैंने शून्य अनुक्रमणिका वाली तालिकाएँ देखी हैं, और मैंने 100 से अधिक तालिकाएँ देखी हैं (मुझे यकीन है कि आप में से कुछ ने अधिक संख्याएँ देखी हैं)। न तो शून्य और न ही 100 अच्छा है, लेकिन "सही" संख्या वह है जिसे आपको उपलब्ध डेटा और अपने अनुभव का उपयोग करके पता लगाना है।