हमारे यहाँ सबसे बड़ी समस्याएँ हैं:
- जैसे @JNK कहता है, SQL सर्वर UDF के उपयोग को दूर करता है, और वैसे भी उनके साथ भयानक काम करता है (जैसे हमेशा एक पंक्ति का अनुमान लगाना)। जब आप SSMS में वास्तविक योजना बनाते हैं, तो आप इसका उपयोग बिल्कुल भी नहीं देखते हैं। प्लान एक्सप्लोरर उसी सीमाओं के अधीन है क्योंकि यह केवल SQL सर्वर द्वारा प्रदान की जाने वाली योजना के बारे में जानकारी प्रदान कर सकता है।
- वास्तविक योजना बनाते समय कोड रनटाइम मैट्रिक्स के लिए विभिन्न स्रोतों पर निर्भर करता है। दुर्भाग्य से योजना एक्सएमएल में फ़ंक्शन कॉल शामिल नहीं होते हैं, और SQL सर्वर किसी फ़ंक्शन का उपयोग करते हुए I / O को प्रकट नहीं करता है
SET STATISTICS IO ON;
(यह इस प्रकार है कि Table I/O
टैब आबाद हो जाता है)।
निम्नलिखित दृश्य पर विचार करें और AdventureWorks2012 के खिलाफ कार्य करें। यह शीर्ष लेख तालिका से एक यादृच्छिक पंक्ति दी गई विवरण तालिका से एक यादृच्छिक पंक्ति को वापस करने का एक मूर्खतापूर्ण प्रयास है - ज्यादातर यह सुनिश्चित करने के लिए कि हम हर बार जितना संभव हो उतना I / O उत्पन्न करते हैं।
CREATE VIEW dbo.myview
WITH SCHEMABINDING
AS
SELECT TOP (100000) rowguid, SalesOrderID, n = NEWID()
FROM Sales.SalesOrderDetail ORDER BY NEWID();
GO
CREATE FUNCTION dbo.whatever(@SalesOrderID INT)
RETURNS UNIQUEIDENTIFIER
WITH SCHEMABINDING
AS
BEGIN
RETURN
(
SELECT TOP (1) rowguid FROM dbo.myview
WHERE SalesOrderID = @SalesOrderID ORDER BY n
);
END
GO
प्रबंधन स्टूडियो क्या करता है (और क्या नहीं) आपको बताता है
SSMS में निम्नलिखित प्रश्न लें:
SET STATISTICS IO ON;
SELECT TOP (5) SalesOrderID, dbo.whatever(SalesOrderID)
FROM Sales.SalesOrderHeader ORDER BY NEWID();
SET STATISTICS IO OFF;
जब आप एक योजना का अनुमान है, आप क्वेरी के लिए एक योजना मिल और एक एकल समारोह के लिए योजना (, नहीं 5 के रूप में आप आशा है कि हो सकता है):
आपको कोई भी I / O डेटा बिल्कुल नहीं मिलता है, जाहिर है, चूंकि क्वेरी वास्तव में निष्पादित नहीं हुई थी। अब, एक वास्तविक योजना बनाएं। परिणाम ग्रिड में आपको अपेक्षित 5 पंक्तियाँ मिलती हैं, निम्न योजना (जो कि यूडीएफ का कोई स्पष्ट उल्लेख नहीं करती है, एक्सएमएल को छोड़कर आप इसे क्वेरी टेक्स्ट के हिस्से और स्केलर ऑपरेटर के हिस्से के रूप में पा सकते हैं):
और निम्नलिखित STATISTICS IO
आउटपुट (जिसका उल्लेख बिल्कुल नहीं है Sales.SalesOrderDetail
, भले ही हम जानते हैं कि इसे उस तालिका से पढ़ना था ):
तालिका 'SalesOrderHeader'। स्कैन काउंट 1, लॉजिकल रीड 57, फिजिकल रीड्स 0, रीड-फॉरवर्ड रीड्स 0, लॉब लॉजिकल रीड्स 0, लॉब फिजिकल रीड्स 0, लॉब रीड-फॉरवर्ड रीड्स 0।
क्या प्लान एक्सप्लोरर आपको बताता है
जब PE समान क्वेरी के लिए अनुमानित योजना बनाता है, तो वह SSMS जैसी ही चीज़ के बारे में जानता है। हालाँकि यह चीजों को थोड़ा और सहज तरीके से दिखाता है। उदाहरण के लिए, बाहरी क्वेरी के लिए अनुमानित योजना से पता चलता है कि फ़ंक्शन के आउटपुट को क्वेरी के आउटपुट के साथ कैसे जोड़ा जाता है, और यह तुरंत स्पष्ट है - एक एकल प्लान आरेख के भीतर - कि दोनों तालिकाओं से I / O है :
यह फ़ंक्शन की योजना को भी खुद से दिखाता है , जिसे मैं केवल पूर्णता के लिए शामिल कर रहा हूं:
अब, एक वास्तविक योजना पर एक नज़र डालते हैं, जो हजारों गुना अधिक उपयोगी है। यहाँ नकारात्मक पक्ष यह है कि फिर से, यह केवल जानकारी है कि SQL सर्वर दिखाने का फैसला करता है, इसलिए यह केवल ग्राफिकल प्लान आरेख (एस) को उजागर कर सकता है जो SQL सर्वर प्रदान करता है। यह ऐसी स्थिति नहीं है जहां किसी ने आपको कुछ उपयोगी नहीं दिखाने का फैसला किया है; यह सिर्फ एक्सएमएल प्रदान की गई योजना के आधार पर इसके बारे में कुछ भी नहीं जानता है। इस मामले में, यह SSMS की तरह ही है , आप केवल बाहरी क्वेरी की योजना देख सकते हैं, और यह ऐसा है जैसे कि फ़ंक्शन को बिल्कुल भी नहीं बुलाया जा रहा है :
तालिका I / O टैब, अभी भी, के आउटपुट पर निर्भर करता हैSTATISTICS IO
, जो फ़ंक्शन कॉल में की गई किसी भी गतिविधि को अनदेखा करता है:
हालाँकि, PE को आपके लिए संपूर्ण कॉल स्टैक मिल जाता है। मैंने कभी-कभी लोगों को यह कहते हुए सुना है, "पफेट, मुझे कब कॉल स्टैक की आवश्यकता होगी?" ठीक है, आप वास्तव में बिताए गए समय को तोड़ सकते हैं , सीपीयू का उपयोग किया जाता है, और प्रत्येक एकल फ़ंक्शन कॉल के लिए रीड (और टीवीएफ के लिए, उत्पादित पंक्तियों की संख्या) पढ़ता है :
दुर्भाग्य से, आपके पास उस तालिका को वापस करने की क्षमता नहीं है जो I / O किस तालिका से आ रही है (फिर से, क्योंकि SQL सर्वर उस जानकारी को प्रदान नहीं करता है), और इसे UDF नाम के साथ लेबल नहीं किया गया है (क्योंकि यह एक तदर्थ कथन के रूप में कैप्चर किया गया है, न कि फ़ंक्शन स्वयं कॉल करता है)। लेकिन यह क्या आप को देखने की अनुमति देता है, कि प्रबंधन स्टूडियो नहीं है, क्या एक कुत्ता आपके UDF है। आपको अभी भी कुछ डॉट्स से जुड़ना है, लेकिन कम डॉट्स हैं और वे एक साथ करीब हैं।
Profiler के बारे में
अंत में, मैं दृढ़ता से प्रोइलर से दूर रहने की सलाह दूंगा, जब तक कि यह सर्वर-साइड ट्रेस सेट करने के लिए नहीं है जो आप स्क्रिप्ट पर जा रहे हैं और फिर किसी भी यूआई टूल के दायरे से बाहर चलाएं। एक उत्पादन प्रणाली के खिलाफ Profiler का उपयोग करना लगभग निश्चित रूप से अधिक समस्याओं का कारण बनने वाला है जितना कि यह कभी भी हल करेगा । यदि आप यह जानकारी प्राप्त करना चाहते हैं, तो कृपया सर्वर-साइड ट्रेस या विस्तारित घटनाओं का उपयोग करें, और बहुत समझदारी से फ़िल्टर करना सुनिश्चित करें। प्रोफाइलर के बिना भी, एक ट्रेस आपके सर्वर को प्रभावित कर सकता है, और विस्तारित घटनाओं के माध्यम से शोप्लांस को फिर से प्राप्त करना दुनिया में सबसे कुशल बात भी नहीं है ।