ما هو الفرق بين درجة الحرارة الجدول متغير الجدول في SQL Server?

StackOverflow https://stackoverflow.com/questions/27894

سؤال

في SQL Server 2005 ، يمكننا إنشاء الجداول temp واحدة من طريقتين:

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

أو

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

ما هي الاختلافات بين هذين ؟ لقد قرأت آراء متضاربة بشأن ما إذا كان @tmp لا يزال يستخدم بيانات ، أو إذا كان كل شيء يحدث في الذاكرة.

في سيناريوهات لا أحد أداء الآخر ؟

هل كانت مفيدة؟

المحلول

هناك عدد قليل من الاختلافات بين الجداول المؤقتة (#tmp) و متغيرات الجدول (@tmp), على الرغم من استخدام بيانات ليست واحدة منها ، على النحو المبين في MSDN الرابط أدناه.

وكقاعدة عامة من الإبهام, للمشاريع الصغيرة والمتوسطة حجم البيانات و بسيطة سيناريوهات الاستخدام يجب عليك استخدام متغيرات الجدول.(هذا هو مفرط التوجيهي مع الكثير من الاستثناءات - انظر أدناه و المقالات التالية.)

بعض النقاط في الاعتبار عند اختيار بينهما:

  • الجداول المؤقتة حقيقية الجداول لذلك يمكنك أن تفعل أشياء مثل إنشاء الفهارس ، إلخ.إذا كان لديك كميات كبيرة من البيانات التي قبل الوصول إلى مؤشر سوف يكون أسرع ثم الجداول المؤقتة هي خيار جيد.

  • الجدول المتغيرات يمكن أن يكون الفهارس باستخدام المفتاح الأساسي أو قيود فريدة.(إذا كنت ترغب في عدم فهرس فريد تشمل فقط عمود المفتاح الأساسي كما العمود الأخير في قيد فريد.إذا لم يكن لديك فريدة من نوعها العمود ، يمكنك استخدام عمود هوية.) SQL 2014 قد غير الفهارس الفريدة جدا.

  • متغيرات الجدول لا تشارك في المعاملات ، SELECTs ضمنا مع NOLOCK.الصفقة السلوك يمكن أن تكون مفيدة جدا ، على سبيل المثال إذا كنت ترغب في التراجع في منتصف الطريق من خلال إجراء ثم متغيرات الجدول بالسكان خلال هذه الصفقة سوف تكون لا تزال مأهولة بالسكان!

  • درجة الحرارة الجداول قد تؤدي الإجراءات المخزنة يتم recompiled ، وربما في كثير من الأحيان.متغيرات الجدول لن.

  • يمكنك إنشاء جدول temp باستخدام SELECT INTO التي يمكن أن تكون أسرع في كتابة (جيد المخصص الاستعلام) و قد تسمح لك للتعامل مع تغيير أنواع البيانات على مر الزمن, منذ كنت لا تحتاج إلى تعريف temp بنية الجدول مقدما.

  • يمكنك تمرير متغيرات الجدول مرة أخرى من الوظائف ، مما يتيح لك لتغليف وإعادة استخدام المنطق أسهل بكثير (على سبيل المثال جعل وظيفة تقسيم السلسلة إلى جدول القيم على بعض التعسفي محدد).

  • باستخدام الجدول المتغيرات داخل الدالات المعرفة من قبل المستخدم تمكن هذه الوظائف ليتم استخدامها على نطاق واسع (انظر إنشاء وظيفة الوثائق للحصول على التفاصيل).إذا كنت تكتب وظيفة يجب عليك استخدام متغيرات الجدول وعلى مدى درجة الحرارة الجداول ما لم يكن هناك حاجة ملحة خلاف ذلك.

  • جدول المتغيرات temp الجداول المخزنة في tempdb.ولكن متغيرات الجدول (منذ عام 2005) الافتراضي إلى جمع قاعدة البيانات الحالية مقابل temp الجداول التي تأخذ ترتيب النسخ الافتراضي tempdb (المرجع).هذا يعني أنك يجب أن تكون على علم من ترتيب المسائل في حالة استخدام الجداول temp الخاص بك db ترتيب يختلف tempdb ، مما يسبب مشاكل إذا كنت ترغب في مقارنة البيانات في الجدول المؤقت مع البيانات في قاعدة البيانات الخاصة بك.

  • العالمية Temp الجداول (##tmp) هي نوع آخر من الجدول المؤقت متاحة لجميع دورات المستخدمين.

بعض مزيد من القراءة:

نصائح أخرى

مجرد النظر في المطالبة في قبول الإجابة على هذا الجدول المتغيرات لا يشارك في قطع الأشجار.

يبدو عموما صحيح أن هناك أي اختلاف في كمية من الأخشاب (على الأقل بالنسبة 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             |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+

في سيناريوهات لا أحد أداء الآخر ؟

أصغر الجداول (أقل من 1000 الصفوف) استخدام متغير temp, خلاف ذلك استخدام الجدول المؤقت.

@wcm - فعلا أحمق اختيار الجدول متغير ليس Ram فقط - يمكن أن يكون جزئيا المخزنة على القرص.

مؤقت الجدول يمكن أن يكون الفهارس, في حين أن الجدول متغير يمكن أن يكون فقط على المؤشر الرئيسي.إذا كانت السرعة هي قضية متغيرات الجدول يمكن أن يكون أسرع ، ولكن من الواضح إذا كان هناك الكثير من الوثائق ، أو الحاجة إلى البحث في الجدول المؤقت من فهرس متفاوت المسافات ، ثم Temp الجدول سيكون أفضل.

خلفية جيدة المادة

  1. الجدول المؤقت:مؤقت الجدول من السهل إنشاء نسخة احتياطية من البيانات.

    الجدول متغير:ولكن الجدول متغير ينطوي على جهد عندما كنا عادة إنشاء العادي الجداول.

  2. الجدول المؤقت:الجدول المؤقت نتيجة يمكن استخدامها من قبل العديد من المستخدمين.

    الجدول متغير:ولكن الجدول متغير يمكن استخدامها من قبل المستخدم الحالي فقط.

  3. الجدول المؤقت:الجدول المؤقت سيتم تخزينها في tempdb.سيجعل حركة مرور شبكة الاتصال.عندما يكون لدينا كبيرة من البيانات في الجدول المؤقت بعد ذلك إلى العمل عبر قاعدة البيانات.مشكلة أداء موجودة.

    الجدول متغير:ولكن متغير الجدول سيتم تخزين في الذاكرة الفعلية لبعض البيانات ، ثم في وقت لاحق عندما يكون حجم الزيادات سيتم نقلها إلى tempdb.

  4. الجدول المؤقت:الجدول المؤقت يمكن أن تفعل كل عمليات DDL.فإنه يسمح إنشاء الفهارس, اسقاط, يغير, الخ.. ،

    الجدول متغير:في حين أن الجدول متغير لن تسمح به DDL العمليات.ولكن الجدول متغير يسمح لنا لإنشاء فهرس متفاوت المسافات فقط.

  5. الجدول المؤقت:درجة الحرارة يمكن استخدام الجدول للدورة الحالية أو العالمية.حتى أن المستخدم متعددة الدورة يمكن الاستفادة من النتائج في الجدول.

    الجدول متغير:ولكن الجدول متغير يمكن استخدام هذا البرنامج.(Stored procedure)

  6. الجدول المؤقت:متغير Temp لا يمكن استخدام المعاملات.عندما نفعل عمليات DML مع جدول temp ومن ثم يمكن التراجع أو تنفيذ المعاملات.

    الجدول متغير:ولكن لا نستطيع أن نفعل ذلك الجدول متغير.

  7. الجدول المؤقت:وظائف لا يمكن استخدام متغير temp.على مدى أكثر لا نستطيع أن نفعل DML العملية في الوظائف .

    الجدول متغير:ولكن وظيفة تتيح لنا استخدام الجدول متغير.ولكن باستخدام الجدول متغير يمكننا أن نفعل ذلك.

  8. الجدول المؤقت:الإجراء المخزن سوف تفعل إعادة تصنيف (لا يمكن استخدام نفس خطة التنفيذ) عندما نستخدم متغير temp لكل الفرعية sequent المكالمات.

    الجدول متغير:في حين أن الجدول متغير لن تفعل مثل هذا.

لكم جميعا الذين يعتقدون أسطورة أن temp المتغيرات في الذاكرة فقط

أولا الجدول متغير ليس بالضرورة المقيمة في الذاكرة.تحت ضغط الذاكرة, الصفحات التي تنتمي إلى جدول متغير يمكن أن تكون دفعت إلى tempdb.

قراءة المقال هنا: TempDB::الجدول متغير vs المحلية المؤقتة الجدول

والفرق الرئيسي الآخر هو أن متغيرات الجدول لا يكون عمود الإحصاءات ، حيث temp الجداول.وهذا يعني أن محسن الاستعلام لا أعرف كم عدد الصفوف في الجدول متغير (عليه التخمينات 1) ، والتي يمكن أن تؤدي إلى غاية غير الأمثل خطط تم إنشاؤها إذا كان الجدول متغير في الواقع لديها عدد كبير من الصفوف.

الاقتباس مأخوذ من ؛ المهنية SQL Server 2012 الداخلية و استكشاف الأخطاء وإصلاحها

الإحصاءات الفرق الكبير بين درجة الحرارة الجداول الجدول المتغيرات الإحصاءات لا يتم إنشاء على متغيرات الجدول.هذا وقد اثنين من كبرى عواقب ، rst فاي وهو أن محسن الاستعلام يستخدم فاي الثابتة تقدير عدد الصفوف في الجدول متغير بصرف النظر عن البيانات التي يحتوي عليها.وعلاوة على ذلك, إضافة أو إزالة البيانات لا يغير تقدير.

الفهارس لا يمكنك إنشاء الفهارس في الجدول المتغيرات على الرغم من أنك يمكن أن إنشاء القيود.وهذا يعني أن طريق إنشاء المفاتيح الأساسية أو فريدة من نوعها القيود يمكن أن يكون الفهارس (كما يتم إنشاء هذه إلى دعم القيود) على متغيرات الجدول.حتى إذا كان لديك قيود ، ولذلك الفهارس التي سيكون لها الإحصاءات الفهارس لن يكون تستخدم عند الاستعلام جمعت لأنها لن تكون موجودة في تجميع الوقت ، كما أنها سوف تسبب recompilations.

مخطط التعديلات مخطط تعديلات ممكنة على مؤقت الجداول ولكن ليس على جدول المتغيرات.على الرغم من أن المخطط modifi الكاتيونات هي ممكن على الجداول المؤقتة ، تجنب استخدامها لأنها تسبب recompilations من البيانات التي تستخدم الجداول.

Temporary Tables versus Table Variables

متغيرات الجدول لا يتم إنشاء في الذاكرة

وهناك سوء فهم الشائع أن الجدول المتغيرات في الذاكرة الهياكل وعلى هذا النحو سوف تؤدي أسرع من الجداول المؤقتة.شكرا على المرور ودعا sys .dm _ db _ الدورة _ المساحة _ الاستخدام ، مما يدل على بيانات الاستخدام من قبل الدورة ، يمكنك إثبات أن الأمر ليس كذلك.بعد إعادة تشغيل SQL Server واضح DMV, قم بتشغيل البرنامج النصي التالي إلى ما تدره rm أن الدورة _ معرف بإرجاع 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 ;

أي واحد للاستخدام ؟

أم لا يمكنك استخدام الجداول المؤقتة أو متغيرات الجدول يجب أن يكون قررت اختبار شامل ، ولكن فمن الأفضل أن تميل نحو مؤقت الجداول الافتراضية لأن هناك عدد أقل بكثير من الأشياء التي يمكن أن تذهب الخطأ.

رأيت العملاء وضع التعليمات البرمجية باستخدام متغيرات الجدول لأنها تم التعامل مع كمية صغيرة من الصفوف و كان أسرع من جدول مؤقت ، ولكن بعد سنوات قليلة كانت هناك مئات من الآلاف من الصفوف في الجدول متغير الأداء كان فظيعا ، لذا حاول أن تسمح بعض القدرة على التخطيط عندما يمكنك جعل الخاص بك القرار!

فرق آخر:

جدول فار يمكن الوصول إليها فقط من البيانات ضمن الإجراء الذي يخلق ذلك من إجراءات أخرى تسمى قبل ذلك الإجراء أو متداخلة ديناميكية SQL (عبر exec أو sp_executesql).

مؤقت الجدول نطاق ، من ناحية أخرى ، يتضمن رمز دعا في إجراءات متداخلة ديناميكية SQL.

إذا كان الجدول التي تم إنشاؤها بواسطة الإجراء الخاص بك يجب أن يكون الوصول إليها من غيرها تسمى إجراءات أو ديناميكية SQL يجب استخدام الجدول المؤقت.هذا يمكن أن يكون مفيد جدا في الحالات المعقدة.

تنظر أيضا أنه يمكنك في كثير من الأحيان استبدال سواء مع مشتقة الجداول التي قد يكون أسرع أيضا.كما هو الحال مع جميع وضبط الأداء ، على الرغم فقط التجارب الفعلية ضد البيانات الفعلية الخاصة بك يمكن أن أقول لكم أفضل نهج الخاص بك استعلام معين.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top