समय-समय पर, एक वार्तालाप सामने आता है जहां लोगों को यह विश्वास हो जाता है कि टिप्पणियों का प्रदर्शन पर प्रभाव पड़ता है या नहीं।
सामान्य तौर पर, मैं कहूंगा कि, नहीं, टिप्पणियां प्रदर्शन को प्रभावित नहीं करती हैं , लेकिन "यह निर्भर करता है" अस्वीकरण के लिए हमेशा जगह होती है। आइए एक नमूना डेटाबेस और जंक से भरी तालिका बनाएं:
CREATE DATABASE CommentTesting; GO USE CommentTesting; GO SELECT TOP (1000) n = NEWID(), * INTO dbo.SampleTable FROM sys.all_columns ORDER BY NEWID(); GO CREATE UNIQUE CLUSTERED INDEX x ON dbo.SampleTable(n); GO
अब, मैं चार संग्रहीत कार्यविधियाँ बनाना चाहता हूँ - एक टिप्पणियों के 20 वर्णों के साथ, एक 2000 के साथ, एक 20,000 के साथ, और एक 200,000 के साथ। और मैं इसे फिर से करना चाहता हूं जहां टिप्पणियां एम्बेडेड हैं * भीतर * प्रक्रिया के भीतर एक क्वेरी स्टेटमेंट, स्वतंत्र होने के विरोध में (जिसका एक्सएमएल योजना पर असर पड़ेगा)। अंत में, मैंने OPTION (RECOMPILE)
. जोड़ने की प्रक्रिया को दोहराया क्वेरी के लिए।
DECLARE @comments nvarchar(max) = N'', @basesql nvarchar(max), @sql nvarchar(max); SELECT TOP (5000) -- * 40 character strings @comments += N'--' + RTRIM(NEWID()) + CHAR(13) + CHAR(10) FROM sys.all_columns; SET @basesql = N'CREATE PROCEDURE dbo.$name$ AS BEGIN SET NOCOUNT ON; /* $comments1$ */ DECLARE @x int; SELECT @x = COUNT(*) /* $comments2$ */ FROM dbo.SampleTable OPTION (RECOMPILE); END'; SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Small_Separate'), N'$comments1$', LEFT(@comments, 20)); EXEC sys.sp_executesql @sql; SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Medium_Separate'), N'$comments1$', LEFT(@comments, 2000)); EXEC sys.sp_executesql @sql; SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Large_Separate'), N'$comments1$', LEFT(@comments, 20000)); EXEC sys.sp_executesql @sql; SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'ExtraLarge_Separate'), N'$comments1$', LEFT(@comments, 200000)); EXEC sys.sp_executesql @sql; SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Small_Embedded'), N'$comments2$', LEFT(@comments, 20)); EXEC sys.sp_executesql @sql; SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Medium_Embedded'), N'$comments2$', LEFT(@comments, 2000)); EXEC sys.sp_executesql @sql; SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Large_Embedded'), N'$comments2$', LEFT(@comments, 20000)); EXEC sys.sp_executesql @sql; SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'ExtraLarge_Embedded'), N'$comments2$', LEFT(@comments, 200000)); EXEC sys.sp_executesql @sql;
अब, मुझे प्रत्येक प्रक्रिया को 100,000 बार चलाने के लिए कोड जनरेट करने की आवश्यकता है, अवधि को sys.dm_exec_procedure_stats
से मापें , और कैश में योजना का आकार भी जांचें।
DECLARE @hammer nvarchar(max) = N''; SELECT @hammer += N' DBCC FREEPROCCACHE; DBCC DROPCLEANBUFFERS; GO EXEC dbo.' + [name] + N'; GO 100000 SELECT [size of ' + [name] + ' (b)] = DATALENGTH(definition) FROM sys.sql_modules WHERE [object_id] = ' + CONVERT(varchar(32),([object_id])) + N'; SELECT [size of ' + [name] + ' (b)] = size_in_bytes FROM sys.dm_exec_cached_plans AS p CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS t WHERE t.objectid = ' + CONVERT(varchar(32),([object_id])) + N'; SELECT N''' + [name] + N''', avg_dur = total_elapsed_time*1.0/execution_count FROM sys.dm_exec_procedure_stats WHERE [object_id] = ' + CONVERT(varchar(32),([object_id])) + N';' FROM sys.procedures WHERE [name] LIKE N'%[_]Separate' OR [name] LIKE N'%[_]Embedded'; PRINT @hammer;
सबसे पहले, आइए प्रक्रिया निकायों के आकार को देखें। यहां कोई आश्चर्य की बात नहीं है, केवल यह पुष्टि करते हुए कि ऊपर मेरे निर्माण कोड ने प्रत्येक प्रक्रिया में टिप्पणियों के अपेक्षित आकार को उत्पन्न किया है:
प्रक्रिया | आकार (बाइट्स) |
---|---|
छोटा_अलग / छोटा_एम्बेडेड | 378 |
मध्यम_अलग / मध्यम_एम्बेडेड | 4,340 |
बड़ा_अलग / बड़ा_अलग | 40,338 |
ExtraLarge_Separate / ExtraLarge_Separate | 400,348 |
अगला, कैश में योजनाएं कितनी बड़ी थीं?
प्रक्रिया | आकार (बाइट्स) |
---|---|
छोटा_अलग / छोटा_एम्बेडेड | 40,360 |
मध्यम_अलग / मध्यम_एम्बेडेड | 40,360 |
बड़ा_अलग / बड़ा_अलग | 40,360 |
ExtraLarge_Separate / ExtraLarge_Separate | 40,360 |
आखिरकार, प्रदर्शन कैसा रहा? बिना OPTION (RECOMPILE)
, यहां औसत निष्पादन समय है, मिलीसेकंड में - सभी प्रक्रियाओं में काफी सुसंगत:
औसत अवधि (मिलीसेकंड) - बिना विकल्प के (RECOMPILE) उन्हें>
स्टेटमेंट-लेवल के साथ OPTION (RECOMPILE)
, हम बिना किसी पुनर्संकलन की तुलना में पूरे बोर्ड में औसत अवधि में लगभग 50% हिट देख सकते हैं, लेकिन फिर भी बहुत सुंदर:
औसत अवधि (मिलीसेकंड) - विकल्प के साथ (RECOMPILE)उन्हें>
दोनों ही मामलों में, जबकि OPTION (RECOMPILE)
संस्करण आम तौर पर धीमा चलता था, वस्तुतः शून्य . था प्रक्रिया के मुख्य भाग में टिप्पणी के आकार की परवाह किए बिना रनटाइम में अंतर।
उच्च संकलन लागतों के बारे में क्या?
इसके बाद, मैं यह देखना चाहता था कि क्या इन बड़ी टिप्पणियों का संकलन लागतों पर बहुत अधिक प्रभाव पड़ेगा, उदाहरण के लिए यदि प्रक्रियाओं को WITH RECOMPILE
बनाया गया था . इसके लिए ऊपर दिए गए निर्माण कोड को खाते में बदलना आसान था। लेकिन इस मामले में, मैं sys.dm_exec_procedure_stats
पर भरोसा नहीं कर सका , क्योंकि यह प्रक्रियाओं के लिए काम नहीं करता है WITH RECOMPILE
. इसलिए परीक्षण के लिए मेरा जनरेशन कोड थोड़ा अलग था, क्योंकि मुझे औसत अवधि को मैन्युअल रूप से ट्रैक करना होगा:
DECLARE @hammer nvarchar(max) = N''; SELECT @hammer += N' DBCC FREEPROCCACHE; DBCC DROPCLEANBUFFERS; SELECT SYSDATETIME(); GO EXEC dbo.' + [name] + N'; GO 100000 SELECT SYSDATETIME();'; PRINT @hammer;
इस मामले में, मैं कैश में योजनाओं के आकार की जांच नहीं कर सका, लेकिन मैं प्रक्रियाओं के औसत रनटाइम को निर्धारित करने में सक्षम था, और टिप्पणी आकार (या, शायद, केवल प्रक्रिया शरीर के आकार) के आधार पर अंतर था:पी>
औसत अवधि (मिलीसेकंड) - प्रक्रिया स्तर पर RECOMPILE के साथउन्हें>
यदि हम उन सभी को एक साथ एक ग्राफ पर रखते हैं, तो यह स्पष्ट है कि WITH RECOMPILE
कितना अधिक महंगा है उपयोग हो सकता है:
औसत अवधि (मिलीसेकंड) - तीनों विधियों की तुलना करना
मैं शायद बाद में इस पर करीब से नज़र डालूंगा कि यह देखने के लिए कि हॉकी स्टिक कहाँ खेलती है - मैं 10,000-वर्ण की वृद्धि में परीक्षण की कल्पना करता हूँ। हालांकि, अभी के लिए, मैं बहुत संतुष्ट हूं कि मैंने प्रश्न का उत्तर दे दिया है।
सारांश
टिप्पणियां वास्तविक, देखने योग्य संग्रहीत कार्यविधि प्रदर्शन से पूरी तरह से असंबंधित प्रतीत होती हैं, सिवाय उस स्थिति को छोड़कर जहां प्रक्रिया को WITH RECOMPILE
परिभाषित किया गया है। . व्यक्तिगत रूप से, मुझे यह अब जंगली में उपयोग नहीं किया जा रहा है, लेकिन वाईएमएमवी। इस विकल्प और कथन-स्तर के बीच सूक्ष्म अंतर के लिए OPTION (RECOMPILE)
, पॉल व्हाइट का लेख देखें, "पैरामीटर सूँघना, एम्बेड करना, और पुनर्मूल्यांकन विकल्प।"
व्यक्तिगत रूप से, मुझे लगता है कि टिप्पणियां किसी के लिए भी बेहद मूल्यवान हो सकती हैं, जिन्हें आपके कोड की समीक्षा, रखरखाव या समस्या निवारण करना है। इसमें आपका भविष्य शामिल है। मैं उचित मात्रा में टिप्पणियों के प्रदर्शन प्रभाव के बारे में चिंता करने के खिलाफ अत्यधिक अनुशंसा करता हूं, और इसके बजाय टिप्पणियों द्वारा प्रदान किए जाने वाले संदर्भ की उपयोगिता को प्राथमिकता देने पर ध्यान केंद्रित करता हूं। जैसा कि ट्विटर पर किसी ने कहा, एक सीमा होती है। यदि आपकी टिप्पणियां युद्ध और शांति के संक्षिप्त संस्करण के बराबर हैं, तो आप इस पर विचार कर सकते हैं - इसके दस्तावेज़ीकरण से कोड को अलग करने के जोखिम पर - उस दस्तावेज़ को कहीं और रखना, और प्रक्रिया बॉडी टिप्पणियों में लिंक का संदर्भ देना।
डिकॉउलिंग के जोखिम को कम करने के लिए, या दस्तावेज़ीकरण और कोड अन्यथा समय के साथ सिंक से बाहर हो जाते हैं, आप प्रत्यय _documentation
के साथ एक दूसरी प्रक्रिया बना सकते हैं। या _comments
, और वहां टिप्पणियां (या कोड का एक टिप्पणी संस्करण) डाल रहे हैं। हो सकता है कि इसे मुख्य प्रकार की सूचियों से बाहर रखने के लिए इसे एक अलग स्कीमा में रखें। कम से कम प्रलेखन डेटाबेस के साथ कहीं भी रहता है, हालांकि यह गारंटी नहीं देता है कि इसे बनाए रखा जाएगा। यह दुर्भाग्यपूर्ण है कि एक सामान्य प्रक्रिया नहीं बनाई जा सकती WITH SCHEMABINDING
, जिस स्थिति में आप स्पष्ट रूप से टिप्पणी प्रक्रिया को स्रोत से जोड़ सकते हैं।