मूल्यों के लिए एक # तालिका का उपयोग करने के लिए एक दृष्टिकोण हो सकता है और एक हैश जॉइन के लिए अनुमति देने के लिए एक डमी इक्विज़न कॉलम भी पेश किया जा सकता है। उदाहरण के लिए:
-- Create a #temp table with a dummy column to match the hash join
-- and the actual column you want
CREATE TABLE #values (dummy INT NOT NULL, Col0 CHAR(1) NOT NULL)
INSERT INTO #values (dummy, Col0)
VALUES (0, 'A'),
(0, 'B'),
(0, 'C')
GO
-- A similar query, but with a dummy equijoin condition to allow for a hash join
SELECT v.Col0,
CASE v.Col0
WHEN 'A' THEN cs.DataA
WHEN 'B' THEN cs.DataB
WHEN 'C' THEN cs.DataC
END AS Col1
FROM ColumnstoreTable cs
JOIN #values v
-- Join your dummy column to any numeric column on the columnstore,
-- multiplying that column by 0 to ensure a match to all #values
ON v.dummy = cs.DataA * 0
प्रदर्शन और क्वेरी योजना
यह दृष्टिकोण निम्नलिखित की तरह एक क्वेरी योजना देता है, और हैश मैच बैच मोड में किया जाता है:
अगर मैं की जगह SELECT
एक साथ बयान SUM
के CASE
कंसोल के लिए उन सभी पंक्तियों स्ट्रीम और फिर कोई वास्तविक 100MM पंक्ति columnstore तालिका मैं चारों ओर झूठ बोल रही है पर क्वेरी चलाने के लिए होने से बचाने के क्रम में बयान, मैं देख काफी अच्छा प्रदर्शन अपेक्षित 300 मिमी उत्पन्न करने के लिए पंक्तियों:
CPU time = 33803 ms, elapsed time = 4363 ms.
और वास्तविक योजना में हैश ज्वाइन का अच्छा समानांतर होना दर्शाता है।
जब सभी पंक्तियों का मूल्य समान होता है, तो हैश के बारे में नोट समांतरिकरण में शामिल होते हैं
इस क्वेरी का प्रदर्शन पूरी तरह से हैश टेबल तक पहुंच में शामिल होने के जांच पक्ष पर प्रत्येक थ्रेड पर बहुत अधिक निर्भर करता है (हैश विभाजन संस्करण के विपरीत, जो सभी पंक्तियों को एक ही थ्रेड में मैप करेगा, यह देखते हुए कि केवल एक अलग मूल्य है के लिए dummy
स्तंभ)।
सौभाग्य से, यह इस मामले में सच है (जैसा कि हम Parallelism
जांच पक्ष पर एक ऑपरेटर की कमी से देख सकते हैं ) और मज़बूती से सच होना चाहिए क्योंकि बैच मोड एक एकल हैश तालिका बनाता है जो थ्रेड्स में साझा किया जाता है। इसलिए, प्रत्येक थ्रेड उनकी पंक्तियों को ले जा सकता है Columnstore Index Scan
और उन्हें उस साझा हैश तालिका से मिला सकता है। SQL Server 2012 में, यह कार्यक्षमता बहुत कम अनुमानित थी क्योंकि एक स्पिल के कारण ऑपरेटर रो मोड में पुनः आरंभ होता है, दोनों बैच मोड का लाभ खो देते हैं और साथ Repartition Streams
ही साथ जॉइन साइड के जांच पक्ष पर एक ऑपरेटर की आवश्यकता होती है जो इस मामले में थ्रेड स्क्यू का कारण होगा। । SQL सर्वर 2014 में बैच मोड में बने रहने के लिए स्पिलिंग की अनुमति देना एक बड़ा सुधार है।
मेरी जानकारी के लिए, पंक्ति मोड में यह साझा हैश तालिका क्षमता नहीं है। हालाँकि, कुछ मामलों में, आमतौर पर बिल्ड साइड पर 100 से कम पंक्तियों के अनुमान के साथ, SQL सर्वर प्रत्येक थ्रेड के लिए हैश तालिका की एक अलग प्रतिलिपि बनाएगा ( Distribute Streams
हैश ज्वाइन में अग्रणी द्वारा पहचाने जाने योग्य )। यह बहुत शक्तिशाली हो सकता है, लेकिन बैच मोड की तुलना में बहुत कम विश्वसनीय है क्योंकि यह आपके कार्डिनैलिटी अनुमानों पर निर्भर करता है और SQL सर्वर प्रत्येक थ्रेड के लिए हैश तालिका की पूरी प्रतिलिपि बनाने की लागत बनाम लाभों का मूल्यांकन करने की कोशिश कर रहा है।
यूनिअन ऑल: एक सरल विकल्प
पॉल व्हाइट ने कहा कि एक और, और संभावित रूप से सरल, विकल्प UNION ALL
प्रत्येक मूल्य के लिए पंक्तियों को संयोजित करने के लिए उपयोग करना होगा । यह संभावना है कि आपकी सर्वश्रेष्ठ शर्त यह मानती है कि गतिशील रूप से इस SQL को बनाना आपके लिए आसान है। उदाहरण के लिए:
SELECT 'A' AS Col0, c.DataA AS Col1
FROM ColumnstoreTable c
UNION ALL
SELECT 'B' AS Col0, c.DataB AS Col1
FROM ColumnstoreTable c
UNION ALL
SELECT 'C' AS Col0, c.DataC AS Col1
FROM ColumnstoreTable c
यह एक योजना भी तैयार करता है जो बैच मोड का उपयोग करने में सक्षम है और मूल उत्तर की तुलना में बेहतर प्रदर्शन प्रदान करता है। (हालांकि दोनों ही मामलों में प्रदर्शन इतना तेज़ है कि किसी भी टेबल पर डेटा का चयन या लेखन जल्दी से अड़चन बन जाता है।) UNION ALL
दृष्टिकोण भी 0. से गुणा करने जैसे खेल खेलने से बचता है। कभी-कभी इसे सरल समझना सबसे अच्छा होता है!
CPU time = 8673 ms, elapsed time = 4270 ms.