मुझे sql सर्वर में एक टेबल चर बनाम अस्थायी तालिका का उपयोग कब करना चाहिए?


298

मैं तालिका चर में अधिक जानकारी सीख रहा हूं। यह कहता है कि अस्थायी टेबल हमेशा डिस्क पर होती है, और टेबल चर स्मृति में होते हैं, कहने का तात्पर्य यह है कि टेबल वेरिएबल का प्रदर्शन टेम्प टेबल से बेहतर है क्योंकि टेबल वेरिएबल टेम्प टेबल की तुलना में कम आईओ संचालन का उपयोग करता है।

लेकिन कभी-कभी, यदि टेबल चर में बहुत सारे रिकॉर्ड हैं जो मेमोरी में समाहित नहीं हो सकते हैं, तो टेबल चर को टेम्‍प टेबल की तरह डिस्क पर रखा जाएगा।

लेकिन मुझे नहीं पता कि "बहुत सारे रिकॉर्ड" क्या हैं। 100,000 रिकॉर्ड? या 1000,000 रिकॉर्ड? मुझे कैसे पता चलेगा कि मैं जिस टेबल वेरिएबल का उपयोग कर रहा हूं वह मेमोरी में है या डिस्क पर है? क्या तालिका चर के पैमाने को मापने के लिए SQL सर्वर 2005 में कोई फ़ंक्शन या टूल है या मुझे यह पता है कि टेबल चर को मेमोरी से डिस्क पर कब डाला जाता है?


5
एक टेबल चर लगभग हमेशा होता है tempDB- कि "स्मृति में" एक मिथक है। इसके अलावा: टेबल वेरिएबल्स को हमेशा क्वेरी ऑप्टिमाइज़र द्वारा एक पंक्ति में रखने के लिए माना जाएगा - यदि आपके पास बहुत अधिक है, तो यह गंभीर रूप से खराब निष्पादन योजनाओं को जन्म दे सकता है।
marc_s

आप इस उपयोगी लग सकता है stackoverflow.com/questions/27894/...
इगोर Borisenko

2
@marc_s - आप उस विवरण में "लगभग" छोड़ सकते हैं। यह हमेशा tempdb(लेकिन पूरी तरह से स्मृति में भी हो सकता है)
मार्टिन स्मिथ

2
SQL 2014 के साथ अब आप मेमोरी में एक टेबल वेरिएबल बना सकते हैं
paparazzo

जवाबों:


362

आपके प्रश्न से पता चलता है कि आपने टेबल चर और अस्थायी तालिकाओं के आस-पास की कुछ आम गलत धारणाओं के आगे घुटने टेक दिए हैं।

मैंने दो ऑब्जेक्ट प्रकारों के बीच अंतर को देखते हुए डीबीए साइट पर काफी व्यापक उत्तर लिखा है । यह डिस्क बनाम मेमोरी के बारे में आपके प्रश्न को भी संबोधित करता है (मैंने दोनों के बीच व्यवहार में कोई महत्वपूर्ण अंतर नहीं देखा)।

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

जहां आपके पास एक विकल्प है कुछ सुझाव नीचे दिए गए हैं (हालांकि सबसे विश्वसनीय तरीका केवल अपने विशिष्ट कार्यभार के साथ दोनों का परीक्षण करना है)।

  1. यदि आपको एक इंडेक्स की आवश्यकता है जो टेबल चर पर नहीं बनाया जा सकता है, तो आपको निश्चित रूप से #temporaryटेबल की आवश्यकता होगी । हालांकि इसका विवरण संस्करण पर निर्भर है। SQL सर्वर 2012 के लिए और तालिका चर पर बनाए जा सकने वाले एकमात्र इंडेक्स के नीचे वे निहित थे जिन्हें एक UNIQUEया PRIMARY KEYबाधा के माध्यम से बनाया गया था । SQL सर्वर 2014 में उपलब्ध विकल्पों के सबसेट के लिए इनलाइन इंडेक्स सिंटैक्स पेश किया CREATE INDEX। फ़िल्टर्ड इंडेक्स स्थितियों को अनुमति देने के लिए इसे बढ़ाया गया है। साथ इंडेक्स INCLUDE-d कॉलम या columnstore अनुक्रमित अभी भी तालिका चर पर बनाने के लिए संभव नहीं हैं।

  2. यदि आप बार-बार तालिका से बड़ी संख्या में पंक्तियों को जोड़ रहे हैं और हटा रहे हैं तो एक #temporaryतालिका का उपयोग करें । यह समर्थन करता है TRUNCATE(जो DELETEबड़ी तालिकाओं की तुलना में अधिक कुशल है ) और इसके अतिरिक्त बाद में आवेषण TRUNCATEउन लोगों की तुलना में बेहतर प्रदर्शन कर सकते हैं, DELETE जैसा कि यहां सचित्र है

  3. यदि आप बड़ी संख्या में पंक्तियों को हटा रहे हैं या अपडेट कर रहे हैं, तो अस्थायी तालिका तालिका चर की तुलना में बेहतर प्रदर्शन कर सकती है - यदि यह पंक्तियों के साझाकरण का उपयोग करने में सक्षम है (उदाहरण के लिए नीचे "पंक्तियों के बंटवारे के प्रभाव" देखें)।
  4. यदि तालिका का उपयोग करने वाली इष्टतम योजना डेटा पर निर्भर होगी तो #temporaryतालिका का उपयोग करें । यह आँकड़ों के निर्माण का समर्थन करता है जो डेटा के अनुसार योजना को गतिशील रूप से पुनर्सृजित करने की अनुमति देता है (हालांकि संग्रहीत प्रक्रियाओं में कैश्ड अस्थायी तालिकाओं के लिए पुनर्संयोजन व्यवहार को अलग से समझने की आवश्यकता है)।
  5. यदि तालिका का उपयोग करते हुए क्वेरी के लिए इष्टतम योजना कभी भी बदलने की संभावना नहीं है, तो आप आंकड़ों के निर्माण और recompiles के ओवरहेड को छोड़ने के लिए एक तालिका चर पर विचार कर सकते हैं (संभवतः जिस योजना को आप चाहते हैं उसे ठीक करने के लिए संकेत की आवश्यकता होगी)।
  6. यदि तालिका में डाले गए डेटा का स्रोत संभावित महंगे SELECTकथन से है, तो विचार करें कि तालिका चर का उपयोग करने से समानांतर योजना का उपयोग करने की संभावना अवरुद्ध हो जाएगी।
  7. यदि आपको बाहरी उपयोगकर्ता लेनदेन के रोलबैक से बचने के लिए तालिका में डेटा की आवश्यकता है, तो तालिका चर का उपयोग करें। इसके लिए एक संभावित उपयोग मामला एक लंबे SQL बैच में विभिन्न चरणों की प्रगति को लॉग कर सकता है।
  8. जब #tempउपयोगकर्ता लेन-देन के भीतर एक तालिका का उपयोग कर ताले को टेबल वेरिएबल्स की तुलना में अधिक समय तक रखा जा सकता है (संभावित रूप से लेन-देन के अंत तक बनाम विवरण का अंत लॉक और अलगाव स्तर पर निर्भर करता है) और यह भी tempdbलेन-देन लॉग के छंटनी को रोक सकता है जब तक कि उपयोगकर्ता लेनदेन समाप्त होता है। तो यह तालिका चर के उपयोग के पक्ष में हो सकता है।
  9. संग्रहीत दिनचर्या के भीतर, टेबल चर और अस्थायी टेबल दोनों को कैश किया जा सकता है। कैश्ड टेबल चर के लिए मेटाडेटा रखरखाव #temporaryतालिकाओं की तुलना में कम है । बॉब वार्ड अपनी tempdbप्रस्तुति में बताते हैं कि यह उच्च संगति की शर्तों के तहत सिस्टम तालिकाओं पर अतिरिक्त विवाद पैदा कर सकता है। इसके अतिरिक्त, जब छोटी मात्रा में डेटा के साथ काम करते हैं तो यह प्रदर्शन के लिए एक औसत दर्जे का अंतर बना सकता है ।

रसेट शेयरिंग के प्रभाव

DECLARE @T TABLE(id INT PRIMARY KEY, Flag BIT);

CREATE TABLE #T (id INT PRIMARY KEY, Flag BIT);

INSERT INTO @T 
output inserted.* into #T
SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY @@SPID), 0
FROM master..spt_values v1, master..spt_values v2

SET STATISTICS TIME ON

/*CPU time = 7016 ms,  elapsed time = 7860 ms.*/
UPDATE @T SET Flag=1;

/*CPU time = 6234 ms,  elapsed time = 7236 ms.*/
DELETE FROM @T

/* CPU time = 828 ms,  elapsed time = 1120 ms.*/
UPDATE #T SET Flag=1;

/*CPU time = 672 ms,  elapsed time = 980 ms.*/
DELETE FROM #T

DROP TABLE #T

2
हाय, मिस्टर मार्टिन स्मिथ। Mi के मामले में मैं सिर्फ Ids मानों के एक सेट को स्टोर प्रक्रिया के अंदर अन्य क्वेरी में उनका उपयोग करना चाहता हूं। तो आप मुझे क्या सलाह देते हैं?
जीनकार्लो फान्टाल्वो

@JeancarloFontalvo - एक मेज पर एक प्राथमिक कुंजी के साथ चर idऔर का उपयोग OPTION (RECOMPILE)शायद उस के लिए ठीक हो जाएगा - लेकिन दोनों का परीक्षण करें।
मार्टिन स्मिथ

क्या मेटाडेटा विवाद, टेम्प टेबल और टेबल चर दोनों के लिए समान है?
सैयद अकील आशिक

@Syed। आम तौर पर टीवी के लिए कम। यदि उपयोगकर्ता लेन-देन के अंदर है तो ताले पहले ही जारी किए जा सकते हैं। बॉब वार्ड लिंक भी देखें।
मार्टिन स्मिथ

73

यदि बहुत कम मात्रा में डेटा (हजारों बाइट) के लिए एक तालिका चर का उपयोग करें

बहुत सारे डेटा के लिए एक अस्थायी तालिका का उपयोग करें

इसके बारे में सोचने का एक और तरीका: यदि आपको लगता है कि आप एक इंडेक्स, स्वचालित आँकड़े, या किसी एसक्यूएल ऑप्टिमाइज़र अच्छाई से लाभ उठा सकते हैं, तो आपका डेटा सेट संभवतः टेबल चर के लिए बहुत बड़ा है।

मेरे उदाहरण में, मैं लगभग 20 पंक्तियों को एक प्रारूप में रखना चाहता था और उन्हें एक समूह के रूप में संशोधित करना चाहता था, उनका उपयोग करने से पहले उन्हें एक स्थायी तालिका / अद्यतन करें। तो एक तालिका चर परिपूर्ण है।

लेकिन मैं एक बार में हजारों पंक्तियों को वापस भरने के लिए एसक्यूएल भी चला रहा हूं, और मैं निश्चित रूप से कह सकता हूं कि अस्थायी टेबल टेबल टेबल की तुलना में बहुत बेहतर प्रदर्शन करते हैं ।

यह विपरीत नहीं है कि सीटीई समान आकार के कारण के लिए एक चिंता का विषय है - अगर सीटीई में डेटा बहुत छोटा है, तो मुझे लगता है कि सीटीई प्रदर्शन उतना ही अच्छा या बेहतर है जितना कि ऑप्टिमाइज़र के साथ आता है, लेकिन अगर यह काफी बड़ा है तो इससे आपको बुरा लगता है।

मेरी समझ ज्यादातर http://www.developerfusion.com/article/84397/table-variables-v-temporary-tables-in-sql-server/ पर आधारित है , जिसमें बहुत अधिक विवरण हैं।


टेकवेवे टेबल वेरिएबल छोटे डेटासेट के लिए ठीक है, लेकिन बड़े डेटासेट के लिए टेम्प टेबल का उपयोग करें। मेरे पास हजारों पंक्तियों के साथ एक क्वेरी है। तालिका चर से अस्थायी तालिका में स्विच करने से, क्वेरी समय 40 से घटकर केवल 5 एस हो जाता है और बाकी सब कुछ बराबर होता है।
लिआंग

42

Microsoft यहाँ कहता है

टेबल चर में वितरण आँकड़े नहीं हैं, वे recompiles ट्रिगर नहीं करेंगे। इसलिए, कई मामलों में, ऑप्टिमाइज़र इस धारणा पर एक क्वेरी योजना बनाएगा कि टेबल चर में कोई पंक्तियाँ नहीं हैं। इस कारण से, यदि आप बड़ी संख्या में पंक्तियों (100 से अधिक) की अपेक्षा करते हैं, तो आपको तालिका चर का उपयोग करने के बारे में सतर्क रहना चाहिए। इस मामले में टेंप टेबल एक बेहतर उपाय हो सकता है।


14

मैं अबेकस से पूरी तरह सहमत हूं (क्षमा करें - टिप्पणी करने के लिए पर्याप्त बिंदु नहीं हैं)।

यह भी ध्यान रखें, यह जरूरी नहीं है कि आपके पास कितने रिकॉर्ड हैं, बल्कि आपके रिकॉर्ड का आकार है।

उदाहरण के लिए, क्या आपने ५० कॉलम प्रत्येक १,००,००० रिकॉर्ड के साथ केवल ५ कॉलम प्रत्येक के साथ १००० रिकॉर्ड के बीच प्रदर्शन अंतर पर विचार किया है?

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


4

परिवर्तनीय तालिका केवल वर्तमान सत्र के लिए उपलब्ध है, उदाहरण के लिए, यदि आपको EXECवर्तमान एक के भीतर किसी अन्य संग्रहीत प्रक्रिया की आवश्यकता है, तो आपको तालिका को पास करना होगा Table Valued Parameterऔर निश्चित रूप से यह प्रदर्शन को प्रभावित करेगा, अस्थायी तालिकाओं के साथ आप केवल इसके साथ कर सकते हैं अस्थायी तालिका नाम पारित करना

एक अस्थायी तालिका का परीक्षण करने के लिए:

  • ओपन मैनेजमेंट स्टूडियो क्वेरी एडिटर
  • एक अस्थायी तालिका बनाएं
  • एक और क्वेरी संपादक विंडो खोलें
  • इस तालिका से "उपलब्ध" का चयन करें

एक चर तालिका का परीक्षण करने के लिए:

  • ओपन मैनेजमेंट स्टूडियो क्वेरी एडिटर
  • एक परिवर्तनीय तालिका बनाएं
  • एक और क्वेरी संपादक विंडो खोलें
  • इस तालिका से चुनें "उपलब्ध नहीं"

कुछ और जो मैंने अनुभव किया है वह यह है: यदि आपके स्कीमा GRANTको टेबल बनाने का विशेषाधिकार नहीं है तो वेरिएबल टेबल का उपयोग करें।


3

घोषित तालिकाओं में डेटा लिखना declare @tbऔर अन्य तालिकाओं के साथ जुड़ने के बाद, मुझे एहसास हुआ कि अस्थायी तालिकाओं की तुलना में प्रतिक्रिया समय tempdb .. # tbबहुत अधिक है।

जब मैं उनके साथ @tb के साथ जुड़ता हूं तो परिणाम को वापस करने के लिए समय अधिक होता है, #tm के विपरीत , रिटर्न लगभग तात्कालिक है।

मैंने 10,000 पंक्तियों के साथ परीक्षण किया और 5 अन्य तालिकाओं के साथ जुड़ गया


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