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 का उपयोग करता है।
विकल्प (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) का उपयोग करना मेरी व्यावसायिक प्रक्रिया का एक उपयुक्त समाधान है।