FOREIGN KEY पर स्पष्ट एकल कुंजी मान के साथ MERGE JOIN (INDEX SCAN) पर काबू पाएं


9

7/11 जोड़ा गया मुद्दा MERGE JOIN के दौरान इंडेक्स स्कैन की वजह से गतिरोध है। इस मामले में एक लेनदेन एफके मूल तालिका में पूरे सूचकांक पर एस लॉक प्राप्त करने की कोशिश कर रहा है, लेकिन पहले एक और लेनदेन सूचकांक के प्रमुख मूल्य पर एक्स लॉक डालता है।

मुझे एक छोटे से उदाहरण के साथ शुरू करते हैं (TSQL2012 DB 70-461 प्रयोग किया जाता है):

CREATE TABLE [Sales].[Orders](
[orderid] [int] IDENTITY(1,1) NOT NULL,
[custid] [int] NULL,
[empid] [int] NOT NULL,
[shipperid] [int] NOT NULL,
... )

कॉलम तदनुसार [custid], [empid], [shipperid]कोरलेटेड पैरामीटर हैं [Sales].[Customers], [HR].[Employees], [Sales].[Shippers]। प्रत्येक मामले में हमारे पास एक पैरेन्ट टेबल में एक संदर्भित कॉलम पर एक संकुल सूचकांक है।

ALTER TABLE [Sales].[Orders]  WITH CHECK ADD  CONSTRAINT [FK_Orders_Customers] FOREIGN KEY([custid]) REFERENCES [Sales].[Customers] ([custid])
ALTER TABLE [Sales].[Orders]  WITH CHECK ADD  CONSTRAINT [FK_Orders_Employees] FOREIGN KEY([empid]) REFERENCES [HR].[Employees] ([empid])
ALTER TABLE [Sales].[Orders]  WITH CHECK ADD  CONSTRAINT [FK_Orders_Shippers] FOREIGN KEY([shipperid])REFERENCES [Sales].[Shippers] ([shipperid])

मैं INSERT [Sales].[Orders] SELECT ... FROMएक और टेबल पर जाने की कोशिश कर रहा हूं, [Sales].[OrdersCache]जिसमें [Sales].[Orders]विदेशी कुंजियों को छोड़कर समान संरचना है । तालिका [Sales].[OrdersCache]का उल्लेख करने के लिए एक और बात महत्वपूर्ण हो सकती है एक क्लस्टर इंडेक्स।

CREATE CLUSTERED INDEX idx_c_OrdersCache ON Sales.OrdersCache ( custid, empid )

जब मुझे उम्मीद है कि मैं कम मात्रा में डेटा डालने की कोशिश कर रहा हूं, तो LOOP JOIN विदेशी चाबियों पर इंडेक्स की तलाश में ठीक काम करता है।

डेटा की उच्च मात्रा के साथ MERGE JOIN क्वेरी ऑप्टिमाइज़र द्वारा क्वेरी में फोरगन कुंजी बनाए रखने के लिए सबसे कुशल तरीके के रूप में उपयोग किया जाता है।

और विदेशी मामलों में हमारे विकल्प (LOOP JOIN) का उपयोग करने से कोई लेना-देना नहीं है या स्पष्ट JOIN मामले में INNER LOOP JOIN है।

नीचे मेरे वातावरण में चलने की कोशिश की जा रही क्वेरी है:

INSERT Sales.Orders (
        custid, empid, shipperid, ... )
SELECT  custid, empid, 2, ...
FROM Sales.OrdersCache

योजना को देखते हुए हम देख सकते हैं कि सभी 3 फ़ोरिंग कुंजियाँ MERGE JOIN के साथ मान्य हैं। यह मेरे लिए एक उपयुक्त तरीका नहीं है क्योंकि यह पूरे सूचकांक लॉकिंग के साथ INDEX SCAN का उपयोग करता है। विदेशी कुंजियों के सत्यापन के दौरान MERGE JOIN

विकल्प (LOOP JOIN) का उपयोग करना isn`t उपयुक्त है क्योंकि इसकी कीमत MERGE JOIN से लगभग 15% अधिक है (मुझे लगता है कि प्रतिगमन डेटा वॉल्यूम बढ़ने के साथ अधिक होगा)।

SELECT स्टेटमेंट में आप shipperidपूरे सम्मिलित सेट के लिए विशेषता के लिए एकल मान देख सकते हैं । मेरी राय में, कम से कम अपरिवर्तनीय विशेषता के लिए सम्मिलित सेट के लिए सत्यापन चरण बनाने का एक तरीका होना चाहिए। कुछ इस तरह:

  • यदि हम वैधता के लिए अपरिभाषित उपसमुच्चय रखते हैं, तो जॉय, मेरिन जॉइन, एचएचएच जॉइन करें।
  • यदि मान्य कॉलम का केवल एक ही स्पष्ट मूल्य है, तो हम केवल एक बार (INDEX SEEK) सत्यापन करते हैं।

क्या कोड संरचनाओं, अतिरिक्त DDL ऑब्जेक्ट्स आदि का उपयोग करके ऊपर की स्थिति को पार करने के लिए कोई सामान्य पैटर्न है?

जोड़ा गया 20/07। समाधान। क्वेरी ऑप्टिमाइज़र पहले से ही MERGE JOIN का उपयोग करके 'एकल कुंजी - विदेशी कुंजी' सत्यापन अनुकूलन करता है। और केवल Sales.Shippers तालिका के लिए बनाता है, एक ही समय में क्वेरी में किसी अन्य जॉइन के लिए LOOP JOIN छोड़कर। चूँकि मेरे पास मूल तालिका में कुछ पंक्तियाँ हैं। क्वेरी ऑप्टिमाइज़र एल्गोरिथ्म में सॉर्ट-मर्ज सम्मिलित करता है और आंतरिक तालिका में प्रत्येक पंक्ति की तुलना केवल एक बार करता है। यदि मेरे तंत्र में एकल कुंजी सत्यापन के दौरान एक मान को प्रभावी ढंग से संसाधित करने के लिए कोई विशेष तंत्र है तो मेरे प्रश्न का उत्तर यही है। यह इतना सटीक निर्णय नहीं है, लेकिन यह कि जिस तरह से SQL सर्वर केस का अनुकूलन करता है।

प्रदर्शन को प्रभावित करने वाली जांच से पता चला है कि मेरे मामले में MERGE JOIN और LOOP JOIN डालने का स्टेटमेंट MERGE JOIN (CPU टाइम रिसोर्स) की निम्न श्रेष्ठता के साथ एक साथ 750 पंक्तियों के साथ लगभग बराबर हो गया। इसलिए OPTION (LOOP JOIN) का उपयोग करना मेरी व्यावसायिक प्रक्रिया का एक उपयुक्त समाधान है।

जवाबों:


8

विकल्प (LOOP JOIN) का उपयोग करना isn`t उपयुक्त है क्योंकि इसकी कीमत MERGE JOIN से लगभग 15% अधिक है

शोपलन आउटपुट में प्रदर्शित लागत प्रतिशत हमेशा अनुकूलन मॉडल के अनुमान हैं, यहां तक ​​कि एक पोस्ट-एक्ज़ीक्यूशन (वास्तविक) योजना में भी। इन लागतों की संभावना आपके विशेष हार्डवेयर पर वास्तविक रनटाइम प्रदर्शन को नहीं दर्शाती है। यह सुनिश्चित करने का एकमात्र तरीका है कि आपके कार्यभार के साथ विकल्पों का परीक्षण किया जाए, जो भी मैट्रिक्स आपके लिए सबसे महत्वपूर्ण है (बीता हुआ समय, सीपीयू उपयोग और इसी तरह)।

मेरे अनुभव में, लूप से ऑप्टिमाइज़र स्विच, विदेशी कुंजी सत्यापन के लिए विलय में शामिल होने के लिए बहुत जल्दी जुड़ जाते हैं। सभी लेकिन सबसे बड़े संचालन में, मैंने पाया है कि लूप बेहतर होने के लिए जुड़ते हैं। और "बड़े" से मेरा मतलब है कि लाखों पंक्तियों में कम से कम, निश्चित रूप से हजार नहीं तो आप अपने प्रश्न के लिए टिप्पणियों में इंगित करें।

मेरी राय में, कम से कम अपरिवर्तनीय विशेषता के लिए सम्मिलित सेट के लिए सत्यापन चरण बनाने का एक तरीका होना चाहिए।

यह सिद्धांत रूप में समझ में आता है, लेकिन योजना-निर्माण तर्क के भीतर आज ऐसा कोई तर्क नहीं है जो विदेशी कुंजी सत्यापन का उपयोग करता है। मौजूदा तर्क व्यापक क्वेरी के लिए जानबूझकर बहुत सामान्य और रूढ़िवादी है; विशिष्ट अनुकूलन परीक्षण को जटिल बनाते हैं और एज-केस बग की संभावना को बढ़ाते हैं।

क्या कोड संरचनाओं, अतिरिक्त DDL ऑब्जेक्ट्स आदि का उपयोग करके ऊपर की स्थिति को पार करने के लिए कोई सामान्य पैटर्न है?

ऐसा नहीं कि मुझे पता नहीं। मर्ज के साथ डेडलॉक जोखिम विदेशी कुंजी सत्यापन में शामिल होता है , जो कि सबसे व्यापक रूप से उपयोग किए जाने वाले संकेत के संकेत के साथ जाना जाता हैOPTION (LOOP JOIN) । विदेशी कुंजी सत्यापन के दौरान साझा किए गए तालों से बचने का कोई तरीका नहीं है, क्योंकि पंक्ति-निर्धारण अलगाव स्तरों के तहत, इन्हें शुद्धता के लिए आवश्यक है।

कोई बेहतर सामान्य उत्तर नहीं है (यदि आप लूप जॉइन्ट की तुलना में हैं) यदि आप कई समवर्ती प्रक्रियाओं के लिए अभिभावकों और बच्चे की तालिकाओं में पंक्तियों को जोड़ने के लिए क्षमता को बनाए रखना चाहते हैं। लेकिन, यदि आप डेटा संशोधनों को क्रमबद्ध करने के लिए तैयार हैं (नहीं पढ़ता है), तो sp_getapplock का उपयोग करना एक विश्वसनीय और सरल तकनीक है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.