SQL सर्वर में एक अस्थायी तालिका और तालिका चर के बीच अंतर क्या है?


390

SQL Server 2005 में, हम दो तरीकों में से एक टेम्‍प टेबल बना सकते हैं:

declare @tmp table (Col1 int, Col2 int);

या

create table #tmp (Col1 int, Col2 int);

इन दोनों में क्या अंतर हैं? मैंने इस पर परस्पर विरोधी राय पढ़ी है कि क्या @tmp अभी भी tempdb का उपयोग करता है, या यदि सब कुछ स्मृति में होता है।

किन परिदृश्यों में एक दूसरे का प्रदर्शन करता है?



2
यहाँ पिनाल दवे ने बहुत अच्छा लिखा है ... blog.sqlauthority.com/2009/12/15/…
sam yi

जवाबों:


392

अस्थायी सारणी (#tmp) और सारणी चर (@tmp) के बीच कुछ अंतर हैं, हालांकि tempdb का उपयोग करना उनमें से एक नहीं है, जैसा कि नीचे MSDN लिंक में दिया गया है।

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

उनके बीच चयन करते समय कुछ बिंदुओं पर विचार:

  • टेम्‍परेरी टेबल्‍स असली टेबल होते हैं इसलिए आप क्रिएट इंडेक्स जैसी चीजें कर सकते हैं, अगर आपके पास बड़ी मात्रा में डेटा है जिसके लिए इंडेक्स द्वारा एक्सेस करना तेज होगा तो टेम्‍परेरी टेबल एक अच्‍छा विकल्‍प है।

  • टेबल वैरिएबल में PRIMARY KEY या UNIQUE बाधाओं का उपयोग करके अनुक्रमित हो सकते हैं। (यदि आप एक गैर-अद्वितीय सूचकांक चाहते हैं, तो अद्वितीय बाधा में अंतिम कॉलम के रूप में प्राथमिक कुंजी कॉलम शामिल करें। यदि आपके पास एक अद्वितीय स्तंभ नहीं है, तो आप एक पहचान कॉलम का उपयोग कर सकते हैं।) SQL 2014 में गैर-अद्वितीय इंडेक्स भी हैं।

  • तालिका चर लेनदेन में भाग नहीं लेते SELECTहैं और इसके साथ निहित हैं NOLOCK। लेन-देन व्यवहार बहुत सहायक हो सकता है, उदाहरण के लिए यदि आप एक प्रक्रिया के माध्यम से लोड करना चाहते हैं तो उस लेन-देन के दौरान आबादी वाले टेबल चर अभी भी आबादी वाले होंगे!

  • अस्थायी तालिकाओं को संग्रहीत प्रक्रियाओं में परिणामित किया जा सकता है, शायद अक्सर। टेबल चर नहीं होगा।

  • आप SELECT INTO का उपयोग करके एक अस्थायी तालिका बना सकते हैं, जो लिखने में तेज हो सकती है (तदर्थ क्वेरी के लिए अच्छा है) और आप समय के साथ बदलते डेटाटैप्स से निपटने की अनुमति दे सकते हैं, क्योंकि आपको अपनी अस्थायी तालिका संरचना को परिभाषित करने की आवश्यकता नहीं है।

  • आप कार्यों से तालिका चर वापस पास कर सकते हैं, जिससे आप तर्क को आसान बनाने और पुन: उपयोग करने में सक्षम हो सकते हैं (जैसे कुछ मनमाने परिसीमन पर मानों की तालिका में एक स्ट्रिंग को विभाजित करने के लिए एक फ़ंक्शन बनाते हैं)।

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

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

  • Global Temp Tables (## tmp) सभी सत्रों और उपयोगकर्ताओं के लिए एक अन्य प्रकार की अस्थायी तालिका है।

कुछ और पढ़ने:


26
तालिका चर में अनुक्रमित हो सकते हैं। बस एक अद्वितीय बाधा पैदा करें, और आप स्वचालित रूप से एक सूचकांक प्राप्त करते हैं। एक बड़ा प्रदर्शन अंतर बनाता है। (यदि आप एक अद्वितीय सूचकांक नहीं चाहते हैं, तो अपने इच्छित फ़ील्ड के अंत में वास्तविक प्राथमिक कुंजी जोड़ें। यदि आपको एक नहीं मिला है, तो एक पहचान कॉलम बनाएं)।
बेन

7
@Ben और SQL Server 2014 गैर-अनूठे अनुक्रमित को तालिका चर पर निर्दिष्ट करने की
मार्टिन स्मिथ

4
लेन-देन से प्रभावित नहीं होने वाले टेबल चर कभी-कभी काम करते हैं। यदि आपके पास रोलबैक के बाद कुछ भी है जिसे आप रखना चाहते हैं, तो आप इसे टेबल चर में रख सकते हैं।
क्विलब्रेकर

3
आंकड़े टेम्प टेबल के लिए बनाए गए हैं, जो क्वेरी प्लान को बेहतर बना सकते हैं, लेकिन टेबल वेरिएबल्स के लिए नहीं। इन आंकड़ों को थोड़ी देर के लिए कैश किया जाता है, साथ ही टेम्‍प टेबल के पन्नों को हटाने के बाद, टेम्‍परेचर टेबल को गिरा दिया जाता है और गलत हो सकता है, कैश्ड टेबल को फिर से सक्रिय किया जाना चाहिए।
माइकल ग्रीन

तालिका चर या तो उपयोगकर्ता-परिभाषित डेटा प्रकार (यदि स्तंभ उपयोगकर्ता-परिभाषित डेटा प्रकार का है) या वर्तमान डेटाबेस के टकराव और नहीं tempdb के डिफ़ॉल्ट टकराव के टकराव के लिए डिफ़ॉल्ट होगा। टेंप टेबल टेम्पेड डिफ़ॉल्ट डिफॉल्ट का उपयोग करेगी। देखें: Technet.microsoft.com/en-us/library/ms188927.aspx
PseudoToad

25

केवल स्वीकृत उत्तर में दावे को देखते हुए कि तालिका चर लॉगिंग में भाग नहीं लेते हैं।

यह आम तौर पर असत्य लगता है कि लॉगिंग की मात्रा में कोई अंतर नहीं है (कम से कम insert/ update/ deleteसंचालन के लिए टेबल पर ही है हालांकि मैंने पाया है कि अतिरिक्त सिस्टम टेबल के कारण संग्रहीत प्रक्रियाओं में कैश्ड अस्थायी वस्तुओं के लिए इस संबंध में कुछ छोटे अंतर हैं। अद्यतन)।

मैंने निम्न संचालन के लिए तालिका @table_variableऔर ए दोनों के खिलाफ लॉगिंग व्यवहार को देखा #temp

  1. सफल सम्मिलित करें
  2. मल्टी रो इंसर्ट जहां कथन बाधा के कारण वापस लुढ़का।
  3. अपडेट करें
  4. हटाएं
  5. पुनःआवंटन

लेनदेन लॉग रिकॉर्ड सभी कार्यों के लिए लगभग समान थे।

तालिका चर संस्करण वास्तव में कुछ है अतिरिक्त , क्योंकि यह एक प्रविष्टि (से और बाद में निकाला गया) को जोड़ा गया हो जाता है लॉग प्रविष्टियों sys.syssingleobjrefsआधार तालिका लेकिन कुल मिलाकर कुछ कम बाइट्स विशुद्ध रूप से आंतरिक नाम के रूप में तालिका चर खपत के लिए के लिए की तुलना में 236 कम बाइट्स लॉग इन किया था #tempतालिकाओं (118 कम nvarcharवर्ण)।

पुन: पेश करने के लिए पूरी स्क्रिप्ट (एकल उपयोगकर्ता मोड और मोड का उपयोग करके शुरू की गई सर्वश्रेष्ठ आवृत्ति sqlcmd)

:setvar tablename "@T" 
:setvar tablescript "DECLARE @T TABLE"

/*
 --Uncomment this section to test a #temp table
:setvar tablename "#T" 
:setvar tablescript "CREATE TABLE #T"
*/

USE tempdb 
GO    
CHECKPOINT

DECLARE @LSN NVARCHAR(25)

SELECT @LSN = MAX([Current LSN])
FROM fn_dblog(null, null) 


EXEC(N'BEGIN TRAN StartBatch
SAVE TRAN StartBatch
COMMIT

$(tablescript)
(
[4CA996AC-C7E1-48B5-B48A-E721E7A435F0] INT PRIMARY KEY DEFAULT 0,
InRowFiller char(7000) DEFAULT ''A'',
OffRowFiller varchar(8000) DEFAULT REPLICATE(''B'',8000),
LOBFiller varchar(max) DEFAULT REPLICATE(cast(''C'' as varchar(max)),10000)
)


BEGIN TRAN InsertFirstRow
SAVE TRAN InsertFirstRow
COMMIT

INSERT INTO $(tablename)
DEFAULT VALUES

BEGIN TRAN Insert9Rows
SAVE TRAN Insert9Rows
COMMIT


INSERT INTO $(tablename) ([4CA996AC-C7E1-48B5-B48A-E721E7A435F0])
SELECT TOP 9 ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM sys.all_columns

BEGIN TRAN InsertFailure
SAVE TRAN InsertFailure
COMMIT


/*Try and Insert 10 rows, the 10th one will cause a constraint violation*/
BEGIN TRY
INSERT INTO $(tablename) ([4CA996AC-C7E1-48B5-B48A-E721E7A435F0])
SELECT TOP (10) (10 + ROW_NUMBER() OVER (ORDER BY (SELECT 0))) % 20
FROM sys.all_columns
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE()
END CATCH

BEGIN TRAN Update10Rows
SAVE TRAN Update10Rows
COMMIT

UPDATE $(tablename)
SET InRowFiller = LOWER(InRowFiller),
    OffRowFiller  =LOWER(OffRowFiller),
    LOBFiller  =LOWER(LOBFiller)


BEGIN TRAN Delete10Rows
SAVE TRAN Delete10Rows
COMMIT

DELETE FROM  $(tablename)
BEGIN TRAN AfterDelete
SAVE TRAN AfterDelete
COMMIT

BEGIN TRAN EndBatch
SAVE TRAN EndBatch
COMMIT')


DECLARE @LSN_HEX NVARCHAR(25) = 
        CAST(CAST(CONVERT(varbinary,SUBSTRING(@LSN, 1, 8),2) AS INT) AS VARCHAR) + ':' +
        CAST(CAST(CONVERT(varbinary,SUBSTRING(@LSN, 10, 8),2) AS INT) AS VARCHAR) + ':' +
        CAST(CAST(CONVERT(varbinary,SUBSTRING(@LSN, 19, 4),2) AS INT) AS VARCHAR)        

SELECT 
    [Operation],
    [Context],
    [AllocUnitName],
    [Transaction Name],
    [Description]
FROM   fn_dblog(@LSN_HEX, null) AS D
WHERE  [Current LSN] > @LSN  

SELECT CASE
         WHEN GROUPING(Operation) = 1 THEN 'Total'
         ELSE Operation
       END AS Operation,
       Context,
       AllocUnitName,
       COALESCE(SUM([Log Record Length]), 0) AS [Size in Bytes],
       COUNT(*)                              AS Cnt
FROM   fn_dblog(@LSN_HEX, null) AS D
WHERE  [Current LSN] > @LSN  
GROUP BY GROUPING SETS((Operation, Context, AllocUnitName),())

परिणाम

+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
|                       |                    |                           |             @TV      |             #TV      |                  |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
| Operation             | Context            | AllocUnitName             | Size in Bytes | Cnt  | Size in Bytes | Cnt  | Difference Bytes |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
| LOP_ABORT_XACT        | LCX_NULL           |                           | 52            | 1    | 52            | 1    |                  |
| LOP_BEGIN_XACT        | LCX_NULL           |                           | 6056          | 50   | 6056          | 50   |                  |
| LOP_COMMIT_XACT       | LCX_NULL           |                           | 2548          | 49   | 2548          | 49   |                  |
| LOP_COUNT_DELTA       | LCX_CLUSTERED      | sys.sysallocunits.clust   | 624           | 3    | 624           | 3    |                  |
| LOP_COUNT_DELTA       | LCX_CLUSTERED      | sys.sysrowsets.clust      | 208           | 1    | 208           | 1    |                  |
| LOP_COUNT_DELTA       | LCX_CLUSTERED      | sys.sysrscols.clst        | 832           | 4    | 832           | 4    |                  |
| LOP_CREATE_ALLOCCHAIN | LCX_NULL           |                           | 120           | 3    | 120           | 3    |                  |
| LOP_DELETE_ROWS       | LCX_INDEX_INTERIOR | Unknown Alloc Unit        | 720           | 9    | 720           | 9    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysallocunits.clust   | 444           | 3    | 444           | 3    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysallocunits.nc      | 276           | 3    | 276           | 3    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syscolpars.clst       | 628           | 4    | 628           | 4    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syscolpars.nc         | 484           | 4    | 484           | 4    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysidxstats.clst      | 176           | 1    | 176           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysidxstats.nc        | 144           | 1    | 144           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysiscols.clst        | 100           | 1    | 100           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysiscols.nc1         | 88            | 1    | 88            | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysobjvalues.clst     | 596           | 5    | 596           | 5    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysrowsets.clust      | 132           | 1    | 132           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysrscols.clst        | 528           | 4    | 528           | 4    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.clst       | 1040          | 6    | 1276          | 6    | 236              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.nc1        | 820           | 6    | 1060          | 6    | 240              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.nc2        | 820           | 6    | 1060          | 6    | 240              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.nc3        | 480           | 6    | 480           | 6    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syssingleobjrefs.clst | 96            | 1    |               |      | -96              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syssingleobjrefs.nc1  | 88            | 1    |               |      | -88              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | Unknown Alloc Unit        | 72092         | 19   | 72092         | 19   |                  |
| LOP_DELETE_ROWS       | LCX_TEXT_MIX       | Unknown Alloc Unit        | 16348         | 37   | 16348         | 37   |                  |
| LOP_FORMAT_PAGE       | LCX_HEAP           | Unknown Alloc Unit        | 1596          | 19   | 1596          | 19   |                  |
| LOP_FORMAT_PAGE       | LCX_IAM            | Unknown Alloc Unit        | 252           | 3    | 252           | 3    |                  |
| LOP_FORMAT_PAGE       | LCX_INDEX_INTERIOR | Unknown Alloc Unit        | 84            | 1    | 84            | 1    |                  |
| LOP_FORMAT_PAGE       | LCX_TEXT_MIX       | Unknown Alloc Unit        | 4788          | 57   | 4788          | 57   |                  |
| LOP_HOBT_DDL          | LCX_NULL           |                           | 108           | 3    | 108           | 3    |                  |
| LOP_HOBT_DELTA        | LCX_NULL           |                           | 9600          | 150  | 9600          | 150  |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysallocunits.clust   | 456           | 3    | 456           | 3    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.syscolpars.clst       | 644           | 4    | 644           | 4    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysidxstats.clst      | 180           | 1    | 180           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysiscols.clst        | 104           | 1    | 104           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysobjvalues.clst     | 616           | 5    | 616           | 5    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysrowsets.clust      | 136           | 1    | 136           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysrscols.clst        | 544           | 4    | 544           | 4    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysschobjs.clst       | 1064          | 6    | 1300          | 6    | 236              |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.syssingleobjrefs.clst | 100           | 1    |               |      | -100             |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | Unknown Alloc Unit        | 135888        | 19   | 135888        | 19   |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_INTERIOR | Unknown Alloc Unit        | 1596          | 19   | 1596          | 19   |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysallocunits.nc      | 288           | 3    | 288           | 3    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.syscolpars.nc         | 500           | 4    | 500           | 4    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysidxstats.nc        | 148           | 1    | 148           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysiscols.nc1         | 92            | 1    | 92            | 1    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysschobjs.nc1        | 844           | 6    | 1084          | 6    | 240              |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysschobjs.nc2        | 844           | 6    | 1084          | 6    | 240              |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysschobjs.nc3        | 504           | 6    | 504           | 6    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.syssingleobjrefs.nc1  | 92            | 1    |               |      | -92              |
| LOP_INSERT_ROWS       | LCX_TEXT_MIX       | Unknown Alloc Unit        | 5112          | 71   | 5112          | 71   |                  |
| LOP_MARK_SAVEPOINT    | LCX_NULL           |                           | 508           | 8    | 508           | 8    |                  |
| LOP_MODIFY_COLUMNS    | LCX_CLUSTERED      | Unknown Alloc Unit        | 1560          | 10   | 1560          | 10   |                  |
| LOP_MODIFY_HEADER     | LCX_HEAP           | Unknown Alloc Unit        | 3780          | 45   | 3780          | 45   |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.syscolpars.clst       | 384           | 4    | 384           | 4    |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.sysidxstats.clst      | 100           | 1    | 100           | 1    |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.sysrowsets.clust      | 92            | 1    | 92            | 1    |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.sysschobjs.clst       | 1144          | 13   | 1144          | 13   |                  |
| LOP_MODIFY_ROW        | LCX_IAM            | Unknown Alloc Unit        | 4224          | 48   | 4224          | 48   |                  |
| LOP_MODIFY_ROW        | LCX_PFS            | Unknown Alloc Unit        | 13632         | 169  | 13632         | 169  |                  |
| LOP_MODIFY_ROW        | LCX_TEXT_MIX       | Unknown Alloc Unit        | 108640        | 120  | 108640        | 120  |                  |
| LOP_ROOT_CHANGE       | LCX_CLUSTERED      | sys.sysallocunits.clust   | 960           | 10   | 960           | 10   |                  |
| LOP_SET_BITS          | LCX_GAM            | Unknown Alloc Unit        | 1200          | 20   | 1200          | 20   |                  |
| LOP_SET_BITS          | LCX_IAM            | Unknown Alloc Unit        | 1080          | 18   | 1080          | 18   |                  |
| LOP_SET_BITS          | LCX_SGAM           | Unknown Alloc Unit        | 120           | 2    | 120           | 2    |                  |
| LOP_SHRINK_NOOP       | LCX_NULL           |                           |               |      | 32            | 1    | 32               |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
| Total                 |                    |                           | 410144        | 1095 | 411232        | 1092 | 1088             |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+

1
+1 बस जिज्ञासा से बाहर (और थोड़ा पेडिक होने के लिए)। यह प्रश्न काफी पुराना (अगस्त 2008) था, इसलिए यह SQL 2005 के बारे में था। अब हम 2011 (अंत) में हैं और नवीनतम SQL 2008 R2 प्लस Denali बीटा है। आपने किस संस्करण का उपयोग किया है?
21

2
@xanatos - 2008. 2005 टेबल चर वास्तव में एक नुकसान में होगा के रूप INSERT ... SELECTमें कम से कम लॉग इन नहीं किया गया था और आप SELECT INTO ... एक टेबल चर नहीं कर सकते ।
मार्टिन स्मिथ

1
धन्यवाद @MartinSmith, लॉगिंग के बारे में दावा हटाने के लिए मेरे उत्तर को अपडेट किया।
रोरी

18

किन परिदृश्यों में एक दूसरे का प्रदर्शन करता है?

छोटे तालिकाओं (1000 से कम पंक्तियों) के लिए एक अस्थायी चर का उपयोग करें, अन्यथा एक अस्थायी तालिका का उपयोग करें।


17
कोई सहायक डेटा? यह सिर्फ अपने आप पर एक जोर के रूप में बहुत उपयोगी नहीं है।
माइकल मायर्स

8
Microsoft 100 पंक्तियों की सीमा की अनुशंसा करता है: msdn.microsoft.com/en-us/library/ms175010.aspx (उत्तम आचरण अनुभाग देखें)।
Artemix

स्पष्टीकरण के लिए नीचे मेरा जवाब देखें ।
वेइहुई गुओ

17

@wcm - वास्तव में टेबल को चुनने के लिए, चर केवल राम नहीं है - यह डिस्क पर आंशिक रूप से संग्रहीत किया जा सकता है।

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

अच्छा पृष्ठभूमि लेख


2
अच्छी पृष्ठभूमि लेख +1। मैं अपना उत्तर हटा रहा हूँ क्योंकि इसे संशोधित करने से बहुत कुछ
छूटेगा

12
  1. टेम्‍प टेबल: एक टेम्‍प टेबल डेटा बनाने और बैक अप करने में आसान है।

    टेबल वेरिएबल: लेकिन टेबल वेरिएबल में वह प्रयास शामिल होता है जब हम सामान्य टेबल बनाते हैं।

  2. टेंप टेबल: टेम्प टेबल रिजल्ट का इस्तेमाल कई यूजर्स कर सकते हैं।

    टेबल वेरिएबल: लेकिन टेबल वेरिएबल का इस्तेमाल करंट यूजर ही कर सकते हैं। 

  3. टेम्प टेबल: टेम्प टेबल को टेम्पर्ड टेबल में स्टोर किया जाएगा। यह नेटवर्क ट्रैफिक बनाएगा। जब हमारे पास अस्थायी तालिका में बड़ा डेटा होता है तो उसे डेटाबेस में काम करना पड़ता है। एक प्रदर्शन मुद्दा मौजूद रहेगा।

    तालिका चर: लेकिन एक तालिका चर कुछ डेटा के लिए भौतिक मेमोरी में संग्रहीत करेगा, फिर बाद में जब आकार बढ़ता है तो इसे टेम्पर्डब में ले जाया जाएगा।

  4. टेंप टेबल: टेंप टेबल सभी डीडीएल ऑपरेशन कर सकते हैं। यह इंडेक्स बनाने, छोड़ने, फेरबदल करने आदि की अनुमति देता है।

    टेबल चर: जबकि टेबल चर डीडीएल संचालन करने की अनुमति नहीं देगा। लेकिन तालिका चर हमें केवल संकुल अनुक्रमणिका बनाने की अनुमति देता है।

  5. टेम्प टेबल: अस्थायी टेबल का उपयोग वर्तमान सत्र या वैश्विक के लिए किया जा सकता है। ताकि एक एकाधिक उपयोगकर्ता सत्र तालिका में परिणामों का उपयोग कर सके।

    टेबल वेरिएबल: लेकिन टेबल वेरिएबल को उस प्रोग्राम तक इस्तेमाल किया जा सकता है। (संग्रहीत प्रक्रिया)

  6. अस्थायी तालिका: अस्थायी चर लेनदेन का उपयोग नहीं कर सकते हैं। जब हम डीएमएल ऑपरेशंस को टेम्प टेबल के साथ करते हैं तो यह रोलबैक हो सकता है या लेनदेन कर सकता है।

    तालिका चर: लेकिन हम इसे तालिका चर के लिए नहीं कर सकते।

  7. अस्थायी तालिका: कार्य अस्थायी चर का उपयोग नहीं कर सकते। अधिक हम कार्यों में डीएमएल ऑपरेशन नहीं कर सकते हैं।

    तालिका चर: लेकिन फ़ंक्शन हमें तालिका चर का उपयोग करने की अनुमति देता है। लेकिन टेबल वेरिएबल का उपयोग करके हम ऐसा कर सकते हैं।

  8. टेंप टेबल: स्टोर की गई प्रक्रिया रीकंप्लीकेशन (उसी निष्पादन योजना का उपयोग नहीं कर सकती है) जब हम हर उप-क्रमिक कॉल के लिए अस्थायी चर का उपयोग करते हैं।

    टेबल वेरिएबल: जबकि टेबल वैरिएबल ऐसा नहीं करेगा।


8

आप सभी के लिए जो इस मिथक को मानते हैं कि अस्थायी चर केवल स्मृति में हैं

सबसे पहले, तालिका चर जरूरी नहीं कि स्मृति निवासी है। मेमोरी प्रेशर के तहत, टेबल वेरिएबल से संबंधित पेजों को टेम्पेडब पर धकेला जा सकता है।

यहां लेख पढ़ें: TempDB :: टेबल चर बनाम स्थानीय अस्थायी तालिका


3
क्या आप दो उत्तरों को संबोधित करते हुए एक उत्तर में अपने उत्तर संपादित कर सकते हैं?
जोशुआ ड्रेक

7

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


2
rowsमें स्तंभ sys.partitionsतालिका चर के लिए बनाए रखा है, तो यह वास्तव में पता है कि कितने पंक्तियों तालिका में हैं है। इसका उपयोग करके देखा जा सकता है OPTION (RECOMPILE)। लेकिन स्तंभ के आँकड़ों की कमी का अर्थ है कि यह विशिष्ट कॉलम की भविष्यवाणी नहीं कर सकता है।
मार्टिन स्मिथ

7

से लिया गया भाव; व्यावसायिक SQL सर्वर 2012 आंतरिक और समस्या निवारण

सांख्यिकी टेम्प टेबल और टेबल चर के बीच मुख्य अंतर यह है कि आँकड़े तालिका चर पर नहीं बनाए जाते हैं। इसके दो प्रमुख परिणाम हैं, जिनमें से फाई rst यह है कि क्वेरी ऑप्टिमाइज़र इसमें मौजूद डेटा के बावजूद तालिका चर में पंक्तियों की संख्या के लिए एक फाई xed आकलन का उपयोग करता है। इसके अलावा, डेटा जोड़ने या निकालने से अनुमान नहीं बदलता है।

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

स्कीमा संशोधन स्कीमा संशोधन अस्थायी तालिकाओं पर संभव हैं, लेकिन तालिका चर पर नहीं। हालाँकि, स्कीमा मोडिफ़ केशन अस्थायी टेबलों पर संभव हैं, उनका उपयोग करने से बचें क्योंकि वे उन बयानों का पुनर्मिलन करते हैं जो तालिकाओं का उपयोग करते हैं।

अस्थायी चर बनाम टेबल चर

टेबल वार्स याद में नहीं बनाए गए हैं

एक आम गलतफहमी है कि टेबल चर स्मृति संरचनाएं हैं और जैसे कि अस्थायी तालिकाओं की तुलना में तेज प्रदर्शन करेंगे । एक DMV के लिए धन्यवाद जिसे sys कहा जाता है। dm _ db _ session_ space _ उपयोग, जो सत्र द्वारा tempdb उपयोग दिखाता है, आप साबित कर सकते हैं कि ऐसा नहीं है । DMV को खाली करने के लिए SQL सर्वर को पुनरारंभ करने के बाद, rm को यह बताने के लिए निम्न स्क्रिप्ट चलाएँ कि आपका सत्र _ id उपयोगकर्ता के लिए 0 रिटर्न देता है _ ऑब्जेक्ट _ आवंटित _ पेज _ काउंट:

SELECT session_id,
database_id,
user_objects_alloc_page_count
FROM sys.dm_db_session_space_usage
WHERE session_id > 50 ;

अब आप जाँच सकते हैं कि एक अस्थायी तालिका एक स्तंभ के साथ बनाने के लिए और एक स्तंभ के साथ इसे पॉप्युलेट करने के लिए निम्न स्क्रिप्ट चलाकर कितनी जगह का उपयोग करता है:

CREATE TABLE #TempTable ( ID INT ) ;
INSERT INTO #TempTable ( ID )
VALUES ( 1 ) ;
GO
SELECT session_id,
database_id,
user_objects_alloc_page_count
FROM sys.dm_db_session_space_usage
WHERE session_id > 50 ;

मेरे सर्वर के परिणामों से संकेत मिलता है कि तालिका को tempdb में एक पृष्ठ आवंटित किया गया था। अब उसी स्क्रिप्ट को चलाएं लेकिन इस बार टेबल वैरिएबल का उपयोग करें:

DECLARE @TempTable TABLE ( ID INT ) ;
INSERT INTO @TempTable ( ID )
VALUES ( 1 ) ;
GO
SELECT session_id,
database_id,
user_objects_alloc_page_count
FROM sys.dm_db_session_space_usage
WHERE session_id > 50 ;

कौन सा उपयोग करें?

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

मैंने ग्राहकों को टेबल चर का उपयोग करते हुए कोड विकसित करते देखा है क्योंकि वे थोड़ी मात्रा में पंक्तियों के साथ काम कर रहे थे, और यह एक अस्थायी तालिका की तुलना में तेज था, लेकिन कुछ साल बाद तालिका चर में सैकड़ों हजारों पंक्तियां थीं और प्रदर्शन भयानक था , तो कोशिश करें और जब आप अपना निर्णय लें तो कुछ क्षमता नियोजन की अनुमति दें!


वास्तव में आंकड़े टेबल चर पर बनाए जाते हैं, देखें stackoverflow.com/questions/42824366/…
YuFeng शेन

4

एक और अंतर:

एक तालिका संस्करण केवल उस प्रक्रिया के भीतर बयानों से पहुँचा जा सकता है जो इसे बनाता है, उस प्रक्रिया या नेस्टेड डायनेमिक SQL (निष्पादन या sp_executesql के माध्यम से) नामक अन्य प्रक्रियाओं से नहीं।

दूसरी ओर एक अस्थायी तालिका का दायरा, जिसे प्रक्रियाओं और नेस्टेड डायनेमिक SQL में कोड शामिल है।

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


2

के बीच मतभेद Temporary Tables (##temp/#temp)और Table Variables (@table)इस प्रकार हैं:

  1. Table variable (@table)में बनाया गया है memory। जबकि, एक Temporary table (##temp/#temp)में बनाया गया है tempdb database। हालाँकि, अगर कोई मेमोरी प्रेशर है तो टेबल वेरिएबल से संबंधित पेजों को टेम्पीडब पर धकेला जा सकता है।

  2. Table variablesमें शामिल नहीं किया जा सकता transactions, logging or locking। यह बनाता है @table faster then #temp। तो टेबल चर तेजी से तो अस्थायी तालिका है।

  3. Temporary tableइसके विपरीत स्कीमा संशोधनों की अनुमति देता है Table variables

  4. Temporary tablesनिर्मित दिनचर्या और बच्चे की दिनचर्या में भी दिखाई देते हैं। जबकि, टेबल चर केवल निर्मित दिनचर्या में दिखाई देते हैं।

  5. Temporary tablesअनुमति दी जाती है CREATE INDEXes, जबकि इसके बजाय Table variablesअनुमति नहीं दी जाती है CREATE INDEXकि वे उपयोग करके सूचकांक कर सकते हैं Primary Key or Unique Constraint


1

इस बात पर भी विचार करें कि आप अक्सर व्युत्पन्न तालिकाओं के साथ दोनों को बदल सकते हैं जो अधिक तेज़ हो सकता है। सभी प्रदर्शन ट्यूनिंग के साथ, हालांकि, आपके वास्तविक डेटा के खिलाफ केवल वास्तविक परीक्षण आपको अपने विशेष प्रश्न के लिए सबसे अच्छा तरीका बता सकते हैं।


1

यह मुझे आश्चर्यचकित करता है कि किसी ने भी इन दोनों के बीच महत्वपूर्ण अंतर का उल्लेख नहीं किया है कि अस्थायी तालिका समानांतर आवेषण का समर्थन करती है जबकि तालिका चर नहीं करती है। आपको निष्पादन योजना से अंतर देखने में सक्षम होना चाहिए। और यहाँ चैनल 9 पर SQL कार्यशालाओं से वीडियो है

यह भी बताता है कि आपको छोटे टेबलों के लिए एक अस्थायी चर का उपयोग क्यों करना चाहिए, अन्यथा टेंपरेचर टेबल का उपयोग करें, जैसा कि SQLMenace ने पहले उत्तर दिया था।

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