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

क्यों क्वेरी ऑप्टिमाइज़र पूरी तरह से अनुक्रमित दृश्य अनुक्रमणिका को अनदेखा करता है?

tl;dr उत्तर:यदि आप NOEXPAND निर्दिष्ट नहीं करते हैं, तो क्वेरी ऑप्टिमाइज़र को पता नहीं है कि आप एक दृश्य से एक साधारण चयन सबमिट कर रहे हैं। इसे कुछ व्यू इंडेक्स के साथ आपकी क्वेरी के विस्तार (जो कि यह सब देखता है) से मेल खाना होगा। शायद यह परेशान नहीं करेगा जब यह कलाकारों के एक समूह के साथ पांच-तरफा जुड़ाव है।

किसी क्वेरी से इंडेक्स मिलान देखना एक कठिन समस्या है, और मेरा मानना ​​है कि क्वेरी इंजन के लिए किसी इंडेक्स से मेल खाने के लिए आपका विचार बहुत जटिल है। अपने प्रश्नों में से एक पर विचार करें:

SELECT ID, Code1 FROM EntityView Where Code1 > 'NR%';

यह आपके लिए स्पष्ट है कि यह एक दृश्य अनुक्रमणिका का उपयोग कर सकता है, लेकिन यह वह क्वेरी नहीं है जिसे क्वेरी इंजन देखता है। यदि आप NOEXPAND निर्दिष्ट नहीं करते हैं, तो दृश्य स्वतः विस्तृत हो जाते हैं, इसलिए क्वेरी इंजन में यही होता है:

SELECT ID, Code1 FROM (
    SELECT e.ID, 'NR'+CAST(c1.CODE as nvarchar(11)) as Code1, 'NR'+CAST(c2.CODE as nvarchar(11)) as Code2, 'NR'+CAST(c3.CODE as nvarchar(11)) as Code3, 'NR'+CAST(c4.CODE as nvarchar(11)) as Code4, 'NR'+CAST(c5.CODE as nvarchar(11)) as Code5
    FROM dbo.Entity e
        inner join  dbo.Classificator1 c1 on e.ID = c1.ID
        inner join  dbo.Classificator2 c2 on e.ID = c2.ID
        inner join  dbo.Classificator3 c3 on e.ID = c3.ID
        inner join  dbo.Classificator4 c4 on e.ID = c4.ID
        inner join  dbo.Classificator5 c5 on e.ID = c5.ID;
) AS V;

क्वेरी इंजन इस जटिल क्वेरी को देखता है, और इसमें जानकारी है (लेकिन शायद दृश्य परिभाषाओं का SQL नहीं) जो परिभाषित किए गए दृश्य अनुक्रमणिका का वर्णन करता है। यह देखते हुए कि इस क्वेरी और व्यू इंडेक्स दोनों में कई जॉइन और कास्ट हैं, मिलान करना एक कठिन काम है।

ध्यान रखें कि आप जानते हैं कि इस क्वेरी और व्यू इंडेक्स में जॉइन और मैच समान हैं, लेकिन क्वेरी प्रोसेसर यह नहीं जानता है। यह इस क्वेरी के साथ वैसा ही व्यवहार करता है जैसे कि यह Classificator3 की पांच प्रतियों में शामिल हो गया हो, या यदि स्तंभों में से एक 'NQ'+CAST(c2.CODE as varchar(12)) था। व्यू इंडेक्स मैचर (यह मानते हुए कि इस जटिल क्वेरी से मेल खाने का कोई प्रयास किया गया है) को इस क्वेरी के हर विवरण को शामिल टेबल पर व्यू इंडेक्स के विवरण से मेल खाना होगा।

क्वेरी इंजन को कुशलतापूर्वक क्वेरी निष्पादित करने के तरीके का पता लगाने के लिए अपने # 1 लक्ष्य के रूप में है। यह शायद पांच-तरफा जुड़ाव और CASTs के प्रत्येक विवरण को एक दृश्य अनुक्रमणिका से मिलाने का प्रयास करने में बहुत समय बिताने के लिए डिज़ाइन नहीं किया गया है।

अगर मुझे अनुमान लगाना था, तो मुझे संदेह है कि व्यू इंडेक्स मैचर देखता है कि क्वेरी के परिणाम कॉलम किसी भी अंतर्निहित तालिका (कास्ट की वजह से) के कॉलम भी नहीं हैं और बस कुछ भी करने की कोशिश नहीं करते हैं। जोड़ा गया :मैं गलत हूँ। मैंने क्वेरी को महंगा बनाने के लिए आंकड़ों को अद्यतन करने के मार्टिन के सुझाव की कोशिश की, और इनमें से कुछ प्रश्नों के लिए NOEXPAND के बिना एक व्यू इंडेक्स का मिलान किया गया। व्यू मैचर जितना मैंने सोचा था उससे कहीं ज्यादा चालाक है! तो मुद्दा यह है कि व्यू मैचर शायद एक जटिल क्वेरी से मिलान करने के लिए कठिन प्रयास करता है यदि इसकी लागत बहुत अधिक है।

क्वेरी इंजन यह पता लगाने में सक्षम होने की अपेक्षा करने के बजाय कि यहां क्या मेल खाता है, NOEXPAND संकेत का उपयोग करें। NOEXPAND बिल्कुल आपका मित्र है, क्योंकि तब क्वेरी इंजन को देखने को मिलता है

SELECT ID, Code1 FROM EntityView Where Code1 > 'NR%';

और फिर इंडेक्स मैचर को देखने के लिए यह तुरंत स्पष्ट है कि एक उपयोगी अनुक्रमणिका है।

(नोट:आपके SQL Fiddle कोड में एक ही तालिका के सभी 5 विदेशी कुंजी संदर्भ हैं, जो संभवत:वह नहीं है जो आप चाहते हैं।)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. एक्सएमएल नोड्स से मूल्यों की क्वेरी कैसे करें?

  2. किसी दिनांक सीमा के भीतर तालिका से सभी दिनांकों का चयन करना और प्रति रिक्त दिनांक में 1 पंक्ति शामिल करना

  3. @@ त्रुटि और/या कोशिश करें - कैच

  4. SSMS संस्करण 18 - कोई डेटाबेस आरेख नहीं

  5. अल्पविराम सीमित परिणाम सेट + SQL क्वेरी