आपके प्रश्न से पता चलता है कि आप टेबल वेरिएबल और अस्थायी टेबल के बारे में कुछ सामान्य गलतफहमियों के शिकार हो गए हैं।
मैंने दो ऑब्जेक्ट प्रकारों के बीच अंतर को देखते हुए डीबीए साइट पर काफी व्यापक उत्तर लिखा है। यह डिस्क बनाम मेमोरी के बारे में आपके प्रश्न को भी संबोधित करता है (मैंने दोनों के बीच व्यवहार में कोई महत्वपूर्ण अंतर नहीं देखा)।
शीर्षक में प्रश्न के संबंध में हालांकि एक स्थानीय अस्थायी तालिका बनाम तालिका चर का उपयोग कब करना है, आपके पास हमेशा कोई विकल्प नहीं होता है। फ़ंक्शंस में, उदाहरण के लिए, केवल टेबल वैरिएबल का उपयोग करना संभव है और यदि आपको चाइल्ड स्कोप में टेबल पर लिखने की आवश्यकता है तो केवल एक #temp
टेबल करेगा (टेबल-वैल्यू पैरामीटर रीड ओनली एक्सेस की अनुमति देता है)।
जहां आपके पास कोई विकल्प है वहां कुछ सुझाव नीचे दिए गए हैं (हालांकि सबसे विश्वसनीय तरीका केवल अपने विशिष्ट कार्यभार के साथ दोनों का परीक्षण करना है)।
-
यदि आपको एक ऐसी अनुक्रमणिका की आवश्यकता है जिसे तालिका चर पर नहीं बनाया जा सकता है तो आपको निश्चित रूप से एक
#temporary
की आवश्यकता होगी टेबल। हालांकि इसका विवरण संस्करण पर निर्भर है। SQL सर्वर 2012 के लिए और टेबल वेरिएबल पर बनाए जा सकने वाले एकमात्र इंडेक्स के नीचेUNIQUE
के माध्यम से अंतर्निहित रूप से बनाए गए थे याप्राथमिक कुंजी
बाधा SQL सर्वर 2014 नेCREATE INDEX
में उपलब्ध विकल्पों के सबसेट के लिए इनलाइन इंडेक्स सिंटैक्स पेश किया . फ़िल्टर्ड इंडेक्स स्थितियों की अनुमति देने के लिए इसे तब से बढ़ा दिया गया है।शामिल करें
. के साथ अनुक्रमणिका -d कॉलम या कॉलमस्टोर इंडेक्स अभी भी टेबल वैरिएबल पर बनाना संभव नहीं है। -
यदि आप तालिका से बड़ी संख्या में पंक्तियों को बार-बार जोड़ और हटा रहे हैं तो
#temporary
का उपयोग करें टेबल। यहTRUNCATE
. का समर्थन करता है (जोDELETE
. से अधिक कुशल है बड़ी टेबल के लिए) और इसके अतिरिक्तTRUNCATE
. के बाद के इंसर्टDELETE
. का अनुसरण करने वालों की तुलना में बेहतर प्रदर्शन कर सकते हैं जैसा कि यहाँ दिखाया गया है। - यदि आप बड़ी संख्या में पंक्तियों को हटा रहे हैं या अपडेट कर रहे हैं तो अस्थायी तालिका तालिका चर की तुलना में बहुत बेहतर प्रदर्शन कर सकती है - यदि यह रोसेट साझाकरण का उपयोग करने में सक्षम है (उदाहरण के लिए नीचे "रोसेट साझाकरण के प्रभाव" देखें) ।
- यदि तालिका का उपयोग करने वाली इष्टतम योजना डेटा के आधार पर भिन्न होगी तो
#temporary
का उपयोग करें टेबल। यह आंकड़ों के निर्माण का समर्थन करता है जो डेटा के अनुसार योजना को गतिशील रूप से पुन:संकलित करने की अनुमति देता है (हालांकि संग्रहीत प्रक्रियाओं में कैश्ड अस्थायी तालिकाओं के लिए पुनर्संकलन व्यवहार को अलग से समझने की आवश्यकता होती है)। - यदि तालिका का उपयोग करने वाली क्वेरी के लिए इष्टतम योजना कभी भी बदलने की संभावना नहीं है तो आप आंकड़ों के निर्माण और पुन:संकलन के ऊपरी हिस्से को छोड़ने के लिए एक तालिका चर पर विचार कर सकते हैं (संभवतः अपनी इच्छित योजना को ठीक करने के लिए संकेतों की आवश्यकता होगी)।
- यदि तालिका में सम्मिलित डेटा का स्रोत संभावित रूप से महंगे
SELECT
. से है बयान तो विचार करें कि एक तालिका चर का उपयोग समानांतर योजना का उपयोग करके इसकी संभावना को अवरुद्ध कर देगा। - यदि आपको बाहरी उपयोगकर्ता लेनदेन के रोलबैक से बचने के लिए तालिका में डेटा की आवश्यकता है तो तालिका चर का उपयोग करें। इसके लिए एक संभावित उपयोग मामला एक लंबे SQL बैच में विभिन्न चरणों की प्रगति को लॉग करना हो सकता है।
#temp
का उपयोग करते समय एक उपयोगकर्ता लेन-देन ताले के भीतर तालिका तालिका चर (संभावित रूप से लेन-देन के अंत तक बनाम बयान के अंत तक लॉक और अलगाव स्तर के प्रकार पर निर्भर) की तुलना में अधिक समय तक आयोजित की जा सकती है और साथ ही यहtempdbकोड के छंटनी को रोक सकती है> उपयोगकर्ता लेनदेन समाप्त होने तक लेनदेन लॉग। तो यह तालिका चर के उपयोग के पक्ष में हो सकता है।
- संग्रहीत दिनचर्या के भीतर, तालिका चर और अस्थायी तालिकाओं दोनों को कैश किया जा सकता है। कैश्ड तालिका चर के लिए मेटाडेटा रखरखाव
#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