এসকিউএল সার্ভারে একটি টেম্প টেবিল এবং টেবিলের ভেরিয়েবলের মধ্যে পার্থক্য কী?


452

এটি বেশ কয়েকটি পৌরাণিক কাহিনী এবং বিরোধী মতামত সহ এমন একটি অঞ্চল বলে মনে হচ্ছে।

সুতরাং এসকিউএল সার্ভারে একটি টেবিল ভেরিয়েবল এবং স্থানীয় অস্থায়ী টেবিলের মধ্যে পার্থক্য কী?


উত্তর:


668

সামগ্রী

সামগ্রী

বিচারকার্য স্থগিত রাখার আদেশ

এই উত্তরটি এসকিউএল সার্ভার 2000-এ প্রবর্তিত "ক্লাসিক" সারণী ভেরিয়েবলগুলি নিয়ে আলোচনা করেছে memory সেগুলির টেবিলের পরিবর্তনশীল দৃষ্টান্তগুলি নীচে আলোচিতগুলির ক্ষেত্রে অনেক দিক থেকে আলাদা! ( আরও বিশদ )।

সংগ্রহস্থলের অবস্থান

কোনও পার্থক্য নেই। দুটোই জমা থাকে tempdb

আমি দেখেছি এটি প্রস্তাবিত হয়েছে যে টেবিলের পরিবর্তনশীলগুলির জন্য এটি সর্বদা ক্ষেত্রে হয় না তবে এটি নীচ থেকে যাচাই করা যেতে পারে

DECLARE @T TABLE(X INT)

INSERT INTO @T VALUES(1),(2)

SELECT sys.fn_PhysLocFormatter(%%physloc%%) AS [File:Page:Slot]
FROM @T

উদাহরণস্বরূপ ফলাফল ( tempdb2 টি সারিতে অবস্থানটি সঞ্চিত রয়েছে)

File:Page:Slot
----------------
(1:148:0)
(1:148:1)

যৌক্তিক অবস্থান

@table_variablesতারা #tempটেবিলগুলি করার চেয়ে বর্তমানের ডাটাবেসের অংশ হিসাবে এমনটি আচরণ করুন। টেবিল ভেরিয়েবলের জন্য (২০০৫ সাল থেকে) কলামের জোটগুলি স্পষ্টভাবে নির্দিষ্ট না করা থাকলে বর্তমান ডাটাবেসের মধ্যে থাকবে যখন #tempটেবিলের জন্য এটি ডিফল্ট কল্যানেশন tempdb( আরও বিশদ ) ব্যবহার করবে । অতিরিক্তভাবে ব্যবহারকারী-সংজ্ঞায়িত ডেটা ধরণের এবং এক্সএমএল সংগ্রহগুলি টেবিলগুলির জন্য ব্যবহার করতে টেম্পিডবিতে থাকতে হবে #tempতবে সারণী ভেরিয়েবলগুলি বর্তমান ডাটাবেস ( উত্স ) থেকে এগুলি ব্যবহার করতে পারে ।

এসকিউএল সার্ভার 2012 অন্তর্ভুক্ত ডেটাবেস পরিচয় করিয়ে দেয়। এইগুলিতে অস্থায়ী সারণীর আচরণের পার্থক্য রয়েছে (এইচ / টি হারুন)

একটি অন্তর্ভুক্ত ডাটাবেসে অস্থায়ী সারণী ডেটা থাকা ডাটাবেসের কোলেশনে জড়িত।

  • অস্থায়ী সারণীগুলির সাথে সম্পর্কিত সমস্ত মেটাডেটা (উদাহরণস্বরূপ, টেবিল এবং কলামের নাম, সূচীপত্র এবং এই জাতীয়) ক্যাটালগের জোটে থাকবে।
  • নামযুক্ত সীমাবদ্ধতা অস্থায়ী সারণীতে ব্যবহার করা যাবে না।
  • অস্থায়ী সারণীগুলি ব্যবহারকারী-সংজ্ঞায়িত প্রকার, এক্সএমএল স্কিমা সংগ্রহ বা ব্যবহারকারী-সংজ্ঞায়িত ফাংশনগুলিকে উল্লেখ করতে পারে না।

বিভিন্ন স্কোপের দৃশ্যমানতা

@table_variablesযে ব্যাচ এবং স্কোপটিতে তারা ঘোষিত হয়েছে কেবল তার মধ্যেই অ্যাক্সেস করা যায়। #temp_tablesশিশু ব্যাচে (নেস্টেড ট্রিগার, পদ্ধতি, execকল) এর মধ্যে অ্যাক্সেসযোগ্য । #temp_tablesবাইরের স্কোপে তৈরি হওয়া ( @@NESTLEVEL=0) ব্যাচগুলিও স্প্যান করতে পারে কারণ তারা অধিবেশন শেষ না হওয়া অবধি স্থির থাকে। শিশু ব্যাচে কোনও ধরণের অবজেক্ট তৈরি করা যায় না এবং কলিং স্কোপে অ্যাক্সেস করা যায় তবে পরবর্তী আলোচনা হিসাবে (গ্লোবাল ##tempটেবিলগুলি যদিও এটি হতে পারে)।

জীবনকাল

@table_variablesDECLARE @.. TABLEবিবৃতি সম্বলিত একটি ব্যাচ কার্যকর করা হলে (সেই ব্যাচের কোনও ব্যবহারকারী কোডের আগে) কার্যকর হয় এবং শেষে স্পষ্টভাবে বাদ দেওয়া হয় imp

যদিও পার্সারটি DECLAREনিখুঁত সৃষ্টি নীচে দেখা যেতে পারে তার আগে আপনি টেবিলের পরিবর্তনশীলটি চেষ্টা ও ব্যবহার করতে পারবেন না।

IF (1 = 0)
BEGIN
DECLARE @T TABLE(X INT)
END

--Works fine
SELECT *
FROM @T

#temp_tablesযখন টিএসকিউএল CREATE TABLEবিবৃতিটি সম্মুখীন হয় তখন স্পষ্টভাবে তৈরি করা হয় এবং DROP TABLEযখন ব্যাচটি শেষ হয় (সাথে যদি কোনও শিশু ব্যাচে তৈরি হয় @@NESTLEVEL > 0) বা সেশনটি অন্যথায় শেষ হয় তখন স্পষ্টভাবে বাদ দেওয়া যায় বা স্পষ্টতই বাদ দেওয়া যায় ।

নোট: সঞ্চিত রুটিনের মধ্যে উভয় ধরণের অবজেক্টকে বারবার নতুন টেবিল তৈরি এবং বাদ দেওয়ার পরিবর্তে ক্যাশে করা যায় । এই ক্যাচিং কখন ঘটতে পারে তার উপর বিধিনিষেধ রয়েছে তবে তবে এটি লঙ্ঘন করা সম্ভব তবে যাইহোক যাইহোক #temp_tablesনিষেধাজ্ঞাগুলি @table_variablesপ্রতিরোধ করতে পারে। ক্যাশে জন্য রক্ষণাবেক্ষণ ওভারহেড #tempটেবিল হয় সামান্য টেবিল ভেরিয়েবলের জন্য তার চেয়ে অনেক বেশী এখানে সচিত্র

অবজেক্ট মেটাডেটা

এটি উভয় ধরণের অবজেক্টের জন্য মূলত একই। এটি সিস্টেম বেস টেবিলগুলিতে সঞ্চিত থাকে tempdb। কোনও #tempটেবিলের জন্য এটি সন্ধান করা আরও সহজ, তবে OBJECT_ID('tempdb..#T')সিস্টেম টেবিলে কী ব্যবহার করতে পারি এবং অভ্যন্তরীণভাবে উত্পন্ন নামটি CREATE TABLEবিবৃতিতে সংজ্ঞায়িত নামের সাথে আরও ঘনিষ্ঠভাবে সম্পর্কযুক্ত । টেবিল ভেরিয়েবলের জন্য object_idফাংশনটি কাজ করে না এবং অভ্যন্তরীণ নামটি সম্পূর্ণরূপে সিস্টেমটি উত্পন্ন হয় যা ভেরিয়েবলের সাথে কোনও সম্পর্ক নেই। নীচে দেখায় মেটাডেটা এখনও রয়েছে তবে একটি (আশাকরি অনন্য) কলামের নাম সন্ধান করে। অনন্য কলামের নামবিহীন সারণীর জন্য অবজেক্ট_আইডি DBCC PAGEযতক্ষণ না খালি হয় তা ব্যবহার করে নির্ধারণ করা যেতে পারে ।

/*Declare a table variable with some unusual options.*/
DECLARE @T TABLE
(
[dba.se] INT IDENTITY PRIMARY KEY NONCLUSTERED,
A INT CHECK (A > 0),
B INT DEFAULT 1,
InRowFiller char(1000) DEFAULT REPLICATE('A',1000),
OffRowFiller varchar(8000) DEFAULT REPLICATE('B',8000),
LOBFiller varchar(max) DEFAULT REPLICATE(cast('C' as varchar(max)),10000),
UNIQUE CLUSTERED (A,B) 
    WITH (FILLFACTOR = 80, 
         IGNORE_DUP_KEY = ON, 
         DATA_COMPRESSION = PAGE, 
         ALLOW_ROW_LOCKS=ON, 
         ALLOW_PAGE_LOCKS=ON)
)

INSERT INTO @T (A)
VALUES (1),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13)

SELECT t.object_id,
       t.name,
       p.rows,
       a.type_desc,
       a.total_pages,
       a.used_pages,
       a.data_pages,
       p.data_compression_desc
FROM   tempdb.sys.partitions AS p
       INNER JOIN tempdb.sys.system_internals_allocation_units AS a
         ON p.hobt_id = a.container_id
       INNER JOIN tempdb.sys.tables AS t
         ON t.object_id = p.object_id
       INNER JOIN tempdb.sys.columns AS c
         ON c.object_id = p.object_id
WHERE  c.name = 'dba.se'

আউটপুট

Duplicate key was ignored.

 +-----------+-----------+------+-------------------+-------------+------------+------------+-----------------------+
| object_id |   name    | rows |     type_desc     | total_pages | used_pages | data_pages | data_compression_desc |
+-----------+-----------+------+-------------------+-------------+------------+------------+-----------------------+
| 574625090 | #22401542 |   13 | IN_ROW_DATA       |           2 |          2 |          1 | PAGE                  |
| 574625090 | #22401542 |   13 | LOB_DATA          |          24 |         19 |          0 | PAGE                  |
| 574625090 | #22401542 |   13 | ROW_OVERFLOW_DATA |          16 |         14 |          0 | PAGE                  |
| 574625090 | #22401542 |   13 | IN_ROW_DATA       |           2 |          2 |          1 | NONE                  |
+-----------+-----------+------+-------------------+-------------+------------+------------+-----------------------+

লেনদেন

অপারেশনগুলি @table_variablesসিস্টেমের লেনদেন হিসাবে পরিচালিত হয়, যে কোনও বাহ্যিক ব্যবহারকারীর লেনদেনের চেয়ে আলাদা, যেখানে সমান #tempটেবিল অপারেশনগুলি ব্যবহারকারীর লেনদেনের অংশ হিসাবে পরিচালিত হবে। এই কারণে একটি ROLLBACKকমান্ড কোনও #tempটেবিলকে প্রভাবিত করবে কিন্তু @table_variableছোঁয়া ছাড়বে ।

DECLARE @T TABLE(X INT)
CREATE TABLE #T(X INT)

BEGIN TRAN

INSERT #T
OUTPUT INSERTED.X INTO @T
VALUES(1),(2),(3)

/*Both have 3 rows*/
SELECT * FROM #T
SELECT * FROM @T

ROLLBACK

/*Only table variable now has rows*/
SELECT * FROM #T
SELECT * FROM @T
DROP TABLE #T

লগিং

উভয়ই tempdbলেনদেন লগে লগ রেকর্ড তৈরি করে । একটি সাধারণ ভুল ধারণাটি হ'ল এটি টেবিল ভেরিয়েবলগুলির ক্ষেত্রে নয় তাই এটির নিচে প্রদর্শিত স্ক্রিপ্টটি এটি একটি সারণী ভেরিয়েবল ঘোষণা করে, কয়েক সারি যুক্ত করে তারপরে সেগুলি আপডেট করে এবং মুছে দেয়।

কারণ টেবিলের ভেরিয়েবলটি তৈরি করা হয় এবং ব্যাচের শুরুতে এবং স্পষ্টতই বাদ দেওয়া হয় সম্পূর্ণ লগিং দেখতে একাধিক ব্যাচ ব্যবহার করা প্রয়োজন।

USE tempdb;

/*
Don't run this on a busy server.
Ideally should be no concurrent activity at all
*/
CHECKPOINT;

GO

/*
The 2nd column is binary to allow easier correlation with log output shown later*/
DECLARE @T TABLE ([C71ACF0B-47E9-4CAD-9A1E-0C687A8F9CF3] INT, B BINARY(10))

INSERT INTO @T
VALUES (1, 0x41414141414141414141), 
       (2, 0x41414141414141414141)

UPDATE @T
SET    B = 0x42424242424242424242

DELETE FROM @T

/*Put allocation_unit_id into CONTEXT_INFO to access in next batch*/
DECLARE @allocId BIGINT, @Context_Info VARBINARY(128)

SELECT @Context_Info = allocation_unit_id,
       @allocId = a.allocation_unit_id 
FROM   sys.system_internals_allocation_units a
       INNER JOIN sys.partitions p
         ON p.hobt_id = a.container_id
       INNER JOIN sys.columns c
         ON c.object_id = p.object_id
WHERE  ( c.name = 'C71ACF0B-47E9-4CAD-9A1E-0C687A8F9CF3' )

SET CONTEXT_INFO @Context_Info

/*Check log for records related to modifications of table variable itself*/
SELECT Operation,
       Context,
       AllocUnitName,
       [RowLog Contents 0],
       [Log Record Length]
FROM   fn_dblog(NULL, NULL)
WHERE  AllocUnitId = @allocId

GO

/*Check total log usage including updates against system tables*/
DECLARE @allocId BIGINT = CAST(CONTEXT_INFO() AS BINARY(8));

WITH T
     AS (SELECT Operation,
                Context,
                CASE
                  WHEN AllocUnitId = @allocId THEN 'Table Variable'
                  WHEN AllocUnitName LIKE 'sys.%' THEN 'System Base Table'
                  ELSE AllocUnitName
                END AS AllocUnitName,
                [Log Record Length]
         FROM   fn_dblog(NULL, NULL) AS D)
SELECT Operation = CASE
                     WHEN GROUPING(Operation) = 1 THEN 'Total'
                     ELSE Operation
                   END,
       Context,
       AllocUnitName,
       [Size in Bytes] = COALESCE(SUM([Log Record Length]), 0),
       Cnt = COUNT(*)
FROM   T
GROUP  BY GROUPING SETS( ( Operation, Context, AllocUnitName ), ( ) )
ORDER  BY GROUPING(Operation),
          AllocUnitName 

রিটার্নস

বিস্তারিত দেখুন

ফলাফলের স্ক্রিনশট

সংক্ষিপ্ত বিবরণ (অন্তর্ভুক্ত ড্রপ এবং সিস্টেম বেস টেবিলগুলির জন্য লগিং অন্তর্ভুক্ত)

ফলাফলের স্ক্রিনশট

যতদূর আমি উভয়টির অপারেশনগুলি প্রায় সমমানের লগিং উত্পন্ন করতে সক্ষম হয়েছি

যতক্ষণ পরিমাণ লগিং খুব অনুরূপ একটি গুরুত্বপুর্ন পার্থক্য হলো লগ এর সাথে সম্পর্কিত রেকর্ড হয় #tempটেবিল আউট সাফ করা যাবে না যতক্ষণ না কোনো ধারণকারী ব্যবহারকারী লেনদেনের তাই শেষ একটি দীর্ঘ চলমান লেনদেনের যে কিছু সময়ে লিখেছেন #tempটেবিল লগ ইন ছাঁটাই প্রতিরোধ করবে tempdbযেহেতু স্বশাসিত লেনদেন টেবিল ভেরিয়েবলের জন্য তৈরি হয় না।

সারণী ভেরিয়েবলগুলি সমর্থন করে না TRUNCATEযাতে লগিং অসুবিধে হতে পারে যখন প্রয়োজন হয় কোনও টেবিল থেকে সমস্ত সারি অপসারণ করা (যদিও খুব ছোট টেবিলের জন্য DELETE যাইহোক আরও ভাল কাজ করতে পারে )

Cardinality

টেবিল ভেরিয়েবলগুলির সাথে জড়িত অনেকগুলি এক্সিকিউশন প্ল্যানস সেগুলি থেকে আউটপুট হিসাবে অনুমান করা একক সারি দেখায়। টেবিলের ভেরিয়েবল বৈশিষ্ট্যগুলি পরীক্ষা করে দেখা যায় যে এসকিউএল সার্ভার বিশ্বাস করে যে টেবিলের ভেরিয়েবলের শূন্য সারি রয়েছে (এটি কেন অনুমান করে যে 1 টি সারি শূন্য সারি টেবিল থেকে নির্গত হবে @ পল হোয়াইট এখানে ব্যাখ্যা করেছেন )।

তবে পূর্ববর্তী বিভাগে প্রদর্শিত ফলাফলগুলি একটি সঠিক rowsগণনা দেখায় sys.partitions। বিষয়টি হ'ল বেশিরভাগ ক্ষেত্রে সারণীটি খালি থাকাকালীন বিবৃতিগুলি রেফারেন্সিং সারণী ভেরিয়েবলগুলি সংকলিত হয়। যদি বিবৃতিটি (পুনরায়) সংকলনের পরে @table_variableপপুলেটেড হয় তবে এটি পরিবর্তে টেবিল কার্ডিনালিটির জন্য ব্যবহৃত হবে (এটি স্পষ্টতার কারণে ঘটতে পারে recompileঅথবা সম্ভবত কারণ বিবৃতিটি অন্য কোনও বস্তুরও উল্লেখ করে যা একটি পিছনে সংকলন বা পুনরায় সংশ্লেষের কারণ হয়))

DECLARE @T TABLE(I INT);

INSERT INTO @T VALUES(1),(2),(3),(4),(5)

CREATE TABLE #T(I INT)

/*Reference to #T means this statement is subject to deferred compile*/
SELECT * FROM @T WHERE NOT EXISTS(SELECT * FROM #T)

DROP TABLE #T

পরিকল্পনা স্থগিত সংকলন অনুসরণ করে যথাযথ আনুমানিক সারি গণনা দেখায়।

সঠিক সারি গণনা দেখায়

এসকিউএল সার্ভার 2012 এসপি 2 এ, ট্রেস পতাকা 2453 চালু করা হয়েছে। আরো বিবরণ "রিলেশনাল ইঞ্জিন" এর অধীনে হয় এখানে

যখন এই ট্রেস পতাকাটি সক্ষম করা হবে এটি খুব শীঘ্রই আরও আলোচিত হিসাবে পরিবর্তিত কার্ডিনালটির অ্যাকাউন্টটি স্বয়ংক্রিয় রিকম্পাইলগুলিকে গ্রহণ করতে পারে।

নোট: সামঞ্জস্যতা স্তরের অ্যাজুরে অন 150 টি বিবৃতি সংকলন এখন প্রথম কার্যকর হওয়া পর্যন্ত পিছিয়ে দেওয়া হয়েছে । এর অর্থ এটি আর শূন্য সারির প্রাক্কলন সমস্যায় পড়বে না।

কোনও কলামের পরিসংখ্যান নেই

আরও সঠিক টেবিলের কার্ডিনালিটির অর্থ এই নয় যে আনুমানিক সারির সংখ্যাটি আরও সঠিক হবে (যদি না সারণীতে সমস্ত সারিগুলিতে অপারেশন না করা হয়)। এসকিউএল সার্ভার টেবিল ভেরিয়েবলের কলামের পরিসংখ্যান মোটেও রক্ষণাবেক্ষণ করে না তাই তুলনা অনুমানের উপর ভিত্তি করে অনুমানের উপর ফিরে আসবে (উদাহরণস্বরূপ যে টেবিলের 10% =কোনও অনন্য কলামের বিপরীতে বা 30% >তুলনা করার জন্য ফিরে আসবে )। এর বিপরীতে কলাম পরিসংখ্যান হয় জন্য বজায় #tempটেবিল।

এসকিউএল সার্ভার প্রতিটি কলামে সংশোধনী সংখ্যার একটি গণনা বজায় রাখে। পরিকল্পনাটি সংকলিত হওয়ার পরে যদি সংশোধন করার সংখ্যাটি পুনঃসংযোগ থ্রেশহোল্ড (আরটি) ছাড়িয়ে যায় তবে পরিকল্পনাটি পুনরায় সংকলন করা হবে এবং পরিসংখ্যান আপডেট করা হবে। আরটি টেবিলের ধরণ এবং আকারের উপর নির্ভর করে।

এসকিউএল সার্ভার ২০০৮ সালে প্ল্যান ক্যাচিং থেকে

আরটি নিম্নরূপে গণনা করা হয়। (এন যখন কোনও কোয়েরি প্ল্যানটি সংকলিত হয় তখন একটি টেবিলের কার্ডিনালিকে বোঝায়))

স্থায়ী টেবিল
- যদি এন <= 500, আরটি = 500.
- যদি এন> 500, আরটি = 500 + 0.20 * এন হয়।

অস্থায়ী টেবিল
- যদি এন <6, আরটি = 6.
- 6 <= এন <= 500, আরটি = 500.
- যদি এন> 500, আরটি = 500 + 0.20 * এন হয়।
সারণী পরিবর্তনশীল
- আরটি বিদ্যমান নেই। সুতরাং, টেবিলের ভেরিয়েবলের কার্ডিনালিতে পরিবর্তনের কারণে পুনরায় সংশোধনগুলি ঘটে না। (তবে নীচে টিএফ 2453 সম্পর্কে নোট দেখুন)

KEEP PLANইঙ্গিতটি জন্য রিটুইট সেট ব্যবহার করা যেতে পারে #tempটেবিল স্থায়ী টেবিলের জন্য সমান।

এই সমস্তটির নিখরচায় প্রভাবটি হ'ল প্রায়শই #tempসারণীর জন্য উত্পন্ন কার্য সম্পাদন পরিকল্পনাগুলি @table_variablesএসকিউএল সার্ভারের সাথে কাজ করার জন্য আরও ভাল তথ্য থাকার কারণে অনেকগুলি সারি জড়িত থাকার চেয়ে তার প্রস্থের আদেশের চেয়ে ভাল হয়।

এনবি 1: টেবিলের ভেরিয়েবলের পরিসংখ্যান নেই তবে ত্রুটিযুক্ত পতাকা 2453 এর অধীনে একটি "পরিসংখ্যান পরিবর্তিত" পুনরায় সংকলন ঘটতে পারে ("তুচ্ছ" পরিকল্পনার জন্য প্রযোজ্য নয়) উপরের টেম্প টেবিলগুলির সাথে প্রদর্শিত একই রিকম্পাইল থ্রেশহোল্ডের অধীনে এটি প্রদর্শিত হবে an অতিরিক্ত এক যে যদি N=0 -> RT = 1। যেমন টেবিল ভেরিয়েবল খালি থাকে তখন সমস্ত বিবৃতি সংকলন করে একটি পুনরায় কম্পাইল করে শেষ হবে এবং TableCardinalityখালি না হলে প্রথমবার কার্যকর করা হলে তা সংশোধন করা হবে । সংকলনের সময় সারণী কার্ডিনালিটি প্ল্যানে সংরক্ষণ করা হয় এবং যদি একই কার্ডিনালিটির সাথে বিবৃতিটি আবার কার্যকর করা হয় (হয় নিয়ন্ত্রণের বিবৃতি প্রবাহের কারণে বা ক্যাশেড পরিকল্পনার পুনরায় ব্যবহারের কারণে) কোনও পুনরায় সংযোগ ঘটে না।

এনবি 2: সঞ্চিত পদ্ধতিতে ক্যাশেড অস্থায়ী টেবিলগুলির জন্য পুনঃসংশোধনের গল্পটি উপরে বর্ণিত তুলনায় আরও জটিল। সমস্ত বেহাল বিবরণগুলির জন্য সঞ্চিত পদ্ধতিতে অস্থায়ী টেবিলগুলি দেখুন ।

Recompiles

পাশাপাশি উপরের বর্ণিত সংশোধন ভিত্তিক রিকম্পাইলগুলি অতিরিক্ত সংকলনের #tempসাথেও যুক্ত করা যেতে পারে কারণ তারা টেবিল ভেরিয়েবলগুলির জন্য নিষিদ্ধ ক্রিয়াকলাপগুলিকে অনুমতি দেয় যা একটি সংকলন ট্রিগার করে (যেমন ডিডিএল পরিবর্তন , )CREATE INDEXALTER TABLE

লক

এটি বলা হয়েছে যে টেবিল ভেরিয়েবলগুলি লকিংয়ে অংশ নেয় না। এই ক্ষেত্রে না হয়. এসএসএমএস বার্তাগুলির ট্যাবটিতে নীচের আউটপুটগুলি চালানো inোকানো বিবৃতিটির জন্য নেওয়া এবং লক হওয়া সম্পর্কিত বিশদ জানায়।

DECLARE @tv_target TABLE (c11 int, c22 char(100))

DBCC TRACEON(1200,-1,3604)

INSERT INTO @tv_target (c11, c22)

VALUES (1, REPLICATE('A',100)), (2, REPLICATE('A',100))

DBCC TRACEOFF(1200,-1,3604)

প্রশ্নের যে জন্য SELECTটেবিল ভেরিয়েবল থেকে পল হোয়াইট মন্তব্য তুলে ধরে এই স্বয়ংক্রিয়ভাবে একটি অন্তর্নিহিত সঙ্গে আসা যে NOLOCKইঙ্গিত। এটি নীচে দেখানো হয়েছে

DECLARE @T TABLE(X INT); 

SELECT X
FROM @T 
OPTION (RECOMPILE, QUERYTRACEON 3604, QUERYTRACEON 8607)

আউটপুট

*** Output Tree: (trivial plan) ***

        PhyOp_TableScan TBL: @T Bmk ( Bmk1000) IsRow: COL: IsBaseRow1002  Hints( NOLOCK )

লকিংয়ের উপর এর প্রভাব তবে খুব সামান্য হতে পারে।

SET NOCOUNT ON;

CREATE TABLE #T( [ID] [int] IDENTITY NOT NULL,
                 [Filler] [char](8000) NULL,
                 PRIMARY KEY CLUSTERED ([ID] DESC))


DECLARE @T TABLE ( [ID] [int] IDENTITY NOT NULL,
                 [Filler] [char](8000) NULL,
                 PRIMARY KEY CLUSTERED ([ID] DESC))

DECLARE @I INT = 0

WHILE (@I < 10000)
BEGIN
INSERT INTO #T DEFAULT VALUES
INSERT INTO @T DEFAULT VALUES
SET @I += 1
END

/*Run once so compilation output doesn't appear in lock output*/
EXEC('SELECT *, sys.fn_PhysLocFormatter(%%physloc%%) FROM #T')

DBCC TRACEON(1200,3604,-1)
SELECT *, sys.fn_PhysLocFormatter(%%physloc%%)
FROM @T

PRINT '--*--'

EXEC('SELECT *, sys.fn_PhysLocFormatter(%%physloc%%) FROM #T')

DBCC TRACEOFF(1200,3604,-1)

DROP TABLE #T

উভয়ের জন্য এসকিউএল সার্ভার একটি বরাদ্দকৃত অর্ডার স্ক্যান ব্যবহার করে তা সূচক কী অর্ডারে এই রিটার্নের ফলাফলের কোনওটিই নয়

আমি উপরের স্ক্রিপ্টটি দু'বার চালিয়েছি এবং দ্বিতীয় রানের ফলাফল নীচে রয়েছে

Process 58 acquiring Sch-S lock on OBJECT: 2:-1325894110:0  (class bit0 ref1) result: OK

--*--
Process 58 acquiring IS lock on OBJECT: 2:-1293893996:0  (class bit0 ref1) result: OK

Process 58 acquiring S lock on OBJECT: 2:-1293893996:0  (class bit0 ref1) result: OK

Process 58 releasing lock on OBJECT: 2:-1293893996:0 

টেবিলের ভেরিয়েবলের জন্য লকিং আউটপুটটি সত্যই অত্যন্ত ন্যূনতম কারণ এসকিউএল সার্ভার কেবলমাত্র বস্তুর উপর একটি স্কিমা স্থিতিশীলতা লক অর্জন করে। তবে কোনও #tempটেবিলের জন্য এটি প্রায় হালকা যে এটি কোনও বস্তুর স্তরের Sলকটি নিয়ে যায়। পাশাপাশি টেবিলগুলির সাথে কাজ করার সময় একটি NOLOCKইঙ্গিত বা READ UNCOMMITTEDবিচ্ছিন্নতা স্তর অবশ্যই স্পষ্টভাবে নির্দিষ্ট করা যেতে পারে #temp

একইভাবে পার্শ্ববর্তী ব্যবহারকারীর লেনদেন লগিংয়ের সাথে ইস্যুটির অর্থ এই হতে পারে যে লকগুলি #tempটেবিলগুলির জন্য দীর্ঘ ধরে রাখা হয় । নীচে স্ক্রিপ্ট সহ

    --BEGIN TRAN;   

    CREATE TABLE #T (X INT,Y CHAR(4000) NULL);

    INSERT INTO #T (X) VALUES(1) 

    SELECT CASE resource_type
             WHEN  'OBJECT' THEN OBJECT_NAME(resource_associated_entity_id, 2)
             WHEN  'ALLOCATION_UNIT' THEN (SELECT OBJECT_NAME(object_id, 2)
                                           FROM  tempdb.sys.allocation_units a 
                                           JOIN tempdb.sys.partitions p ON a.container_id = p.hobt_id
                                           WHERE  a.allocation_unit_id = resource_associated_entity_id)
             WHEN 'DATABASE' THEN DB_NAME(resource_database_id)                                      
             ELSE (SELECT OBJECT_NAME(object_id, 2)
                   FROM   tempdb.sys.partitions
                   WHERE  partition_id = resource_associated_entity_id)
           END AS object_name,
           *
    FROM   sys.dm_tran_locks
    WHERE  request_session_id = @@SPID

    DROP TABLE #T

   -- ROLLBACK  

যখন উভয় ক্ষেত্রে সুস্পষ্ট ব্যবহারকারীর লেনদেনের বাইরে চালানো হয় তখন চেক করা sys.dm_tran_locksহয় যখন লক হয় একটি ভাগ করা লক DATABASE

সংক্ষিপ্তকরণের পরে ২ r BEGIN TRAN ... ROLLBACKটি সারি দেখানো হয়েছে যে ললগুলি দুটি বস্তুতে এবং সিস্টেম টেবিলের সারিগুলিতে রোলব্যাকের অনুমতি দেওয়ার জন্য এবং অন্য লেনদেনকে অনির্ধারিত ডেটা পড়া থেকে আটকাতে দেখানো হয়েছে। সমতুল্য টেবিল ভেরিয়েবল অপারেশন ব্যবহারকারীর লেনদেনের সাথে রোলব্যাক সাপেক্ষে নয় এবং পরবর্তী বিবৃতিটি পরীক্ষা করার জন্য আমাদের কাছে এই লকগুলি ধরে রাখার দরকার নেই তবে প্রোফাইলারে লক অর্জিত এবং প্রকাশ করা হয়েছে বা ট্রেস পতাকা ব্যবহার করে 1200 দেখায় যে প্রচুর লকিং ইভেন্ট এখনও রয়েছে ঘটতে পারে।

ইনডেক্সে

এসকিউএল সার্ভার ২০১৪ এর পূর্ববর্তী সংস্করণগুলির জন্য সূচীগুলি কেবল অনন্য বাধা বা প্রাথমিক কী যুক্ত করার পার্শ্ব প্রতিক্রিয়া হিসাবে কেবল টেবিলের ভেরিয়েবলগুলিতে স্পষ্টভাবে তৈরি করা যেতে পারে। এর অবশ্যই অর্থ এই নয় যে কেবল অনন্য সূচকগুলিই সমর্থিত। কোনও অনন্য ক্লাস্টারযুক্ত সূচকের সাথে একটি টেবিলের কোনও অ-অনন্য নন-ক্লাস্টারড ইনডেক্সটি কেবল এটি ঘোষণা করে UNIQUE NONCLUSTEREDএবং পছন্দসই এনসিআই কী (সিকিউএল সার্ভার) এরপরে সিআই কী যুক্ত করে অনুলিপি দেওয়া যেতে পারে তবে কোনও অনন্য না হলেও এমনকি পর্দার আড়ালে এটি করবে এনসিআই নির্দিষ্ট করা যেতে পারে)

প্রদর্শিত আগের বিভিন্ন হিসাবে index_optionগুলি বাধ্যতা ঘোষণায় সুনির্দিষ্ট করা যেতে পারে সহ DATA_COMPRESSION, IGNORE_DUP_KEYএবং FILLFACTOR(যদিও সেখানে সেটিং এটি হিসাবে শুধুমাত্র সূচক কোন পার্থক্য পুনর্নির্মাণের করতে হবে এবং আপনার টেবিল ভেরিয়েবল উপর ইনডেক্স পুনর্নির্মাণের করতে পারবে না কোন বিন্দু আছে!)

অতিরিক্তভাবে সারণী ভেরিয়েবলগুলি INCLUDEডি কলাম, ফিল্টারড ইনডেক্স (2016 অবধি) বা বিভাজন সমর্থন করে না , #tempসারণীগুলি করে (পার্টিশন স্কিমটি অবশ্যই তৈরি করতে হবে tempdb)।

এসকিউএল সার্ভার ২০১৪-তে সূচি

অ-স্বতন্ত্র সূচকগুলি এসকিউএল সার্ভার ২০১৪-এ সারণির ভেরিয়েবল সংজ্ঞায় ইনলাইন হিসাবে ঘোষণা করা যেতে পারে this এর উদাহরণ বাক্য গঠন নিচে।

DECLARE @T TABLE (
C1 INT INDEX IX1 CLUSTERED, /*Single column indexes can be declared next to the column*/
C2 INT INDEX IX2 NONCLUSTERED,
       INDEX IX3 NONCLUSTERED(C1,C2) /*Example composite index*/
);

এসকিউএল সার্ভার ২০১ Ind-তে সূচি

সিটিপি ৩.১ থেকে এখন টেবিল ভেরিয়েবলের জন্য ফিল্টারড সূচকগুলি ঘোষণা করা সম্ভব। আরটিএম দ্বারা এটি এমন ক্ষেত্রে হতে পারে যা অন্তর্ভুক্ত কলামগুলিকেও অনুমতি দেওয়া হয় তবে তারা সংস্থানীয় সংস্থাগুলির কারণে সম্ভবত এটি এসকিউএল 16 এ তৈরি করে না

DECLARE @T TABLE
(
c1 INT NULL INDEX ix UNIQUE WHERE c1 IS NOT NULL /*Unique ignoring nulls*/
)

উপমা

যে প্রশ্নের সন্নিবেশ করান (বা অন্যথায় সংশোধন করা) এর মধ্যে @table_variablesএকটি সমান্তরাল পরিকল্পনা থাকতে পারে না, #temp_tablesএই পদ্ধতিতে সীমাবদ্ধ নয়।

নিম্নরূপে পুনরায় লেখার ক্ষেত্রে একটি আপাত কাজ রয়েছে যে SELECTঅংশটি সমান্তরালভাবে সঞ্চালনের অনুমতি দেয় তবে এটি একটি গোপন অস্থায়ী টেবিল ব্যবহার করে শেষ হয় (পর্দার আড়ালে)

INSERT INTO @DATA ( ... ) 
EXEC('SELECT .. FROM ...')

আমার উত্তরটিতে চিত্রিত হিসাবে সারণী ভেরিয়েবলগুলি থেকে নির্বাচন করে এমন প্রশ্নের মধ্যে এমন কোনও সীমাবদ্ধতা নেই

অন্যান্য কার্যকরী পার্থক্য

  • #temp_tablesএকটি ফাংশন ভিতরে ব্যবহার করা যাবে না। @table_variablesস্কেলার বা মাল্টি-স্টেটমেন্ট টেবিল ইউডিএফগুলির ভিতরে ব্যবহার করা যেতে পারে।
  • @table_variables নাম বাধা থাকতে পারে না।
  • @table_variablesযাবে না SELECT-ed INTO, ALTER-ed, TRUNCATEঘ বা লক্ষ্য হতে DBCCযেমন কমান্ড DBCC CHECKIDENTবা SET IDENTITY INSERTএবং যেমন টেবিল নির্দেশ সমর্থন করি নাWITH (FORCESCAN)
  • CHECK সারণী ভেরিয়েবলের সীমাবদ্ধতাগুলি সরলকরণের জন্য অপ্টিমাইজার দ্বারা বিবেচিত হয় না, অন্তর্নিহিত পূর্বাভাস বা বৈপরীত্য সনাক্তকরণ।
  • সারণী ভেরিয়েবলগুলি রো-সেট ভাগ করে নেওয়ার অপ্টিমাইজেশনের জন্য যোগ্য বলে মনে হচ্ছে না যার অর্থ এইগুলির বিরুদ্ধে পরিকল্পনা মোছা এবং আপডেট করা আরও ওভারহেড এবং PAGELATCH_EXঅপেক্ষা করতে পারে । ( উদাহরণ )

শুধু স্মৃতি?

শুরুতেই বলা আছে উভয় পৃষ্ঠায় সঞ্চিত হন tempdb। তবে এই পৃষ্ঠাগুলিকে ডিস্কে লেখার ক্ষেত্রে আচরণে কোনও পার্থক্য রয়েছে কিনা তা আমি চিহ্নিত করিনি।

আমি এখন এটির উপর একটি সামান্য পরিমাণে পরীক্ষা করেছি এবং এখন পর্যন্ত এরকম কোনও পার্থক্য দেখিনি। সুনির্দিষ্ট পরীক্ষায় আমি এসকিউএল সার্ভারের 2502 পৃষ্ঠাগুলির আমার উদাহরণটি দিয়েছিলাম যা ডেটা ফাইলটিতে লেখা হওয়ার আগে কাট অফ পয়েন্ট বলে মনে হয়।

এনবি: নীচের আচরণটি আর এসকিউএল সার্ভার 2014 বা এসকিউএল সার্ভার 2012 এসপি 1 / সিই 10 বা এসপি 2 / সিই 1 তে ঘটে না আগ্রহী লেখক আর ডিস্কে পৃষ্ঠা লেখার জন্য আগ্রহী নয়। এসকিউএল সার্ভারে এই পরিবর্তন সম্পর্কে আরও বিশদ 2014: টেম্পিডবি লুকানো পারফরম্যান্স রত্ন

নিচের স্ক্রিপ্টটি চলছে

CREATE TABLE #T(X INT, Filler char(8000) NULL)
INSERT INTO #T(X)
SELECT TOP 250 ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values
DROP TABLE #T

এবং মনিটরিং tempdbপ্রসেস মনিটরের সাথে ডেটা ফাইলটিতে লেখেন আমি কিছুই দেখি না (ally৩,28২ off অফসেটে ডেটাবেস বুট পৃষ্ঠায় মাঝে মধ্যে কিছু থাকে)। পরিবর্তন করার পরে 250করতে 251আমি নিচে লেখেন দেখতে শুরু করেন।

ProcMon

উপরের স্ক্রিনশটটি 5 * 32 পৃষ্ঠার লিখিত এবং একটি একক পৃষ্ঠার লিখিত চিত্র দেখায় যে 161 পৃষ্ঠাগুলির ডিস্কে লেখা হয়েছিল। টেবিল ভেরিয়েবলগুলি পরীক্ষা করার সময় আমি 250 পাতার একই কাট অফ পয়েন্ট পেয়েছি। নীচের স্ক্রিপ্টটি দেখে এটি অন্যভাবে দেখায়sys.dm_os_buffer_descriptors

DECLARE @T TABLE (
  X        INT,
  [dba.se] CHAR(8000) NULL)

INSERT INTO @T
            (X)
SELECT TOP 251 Row_number() OVER (ORDER BY (SELECT 0))
FROM   master..spt_values

SELECT is_modified,
       Count(*) AS page_count
FROM   sys.dm_os_buffer_descriptors
WHERE  database_id = 2
       AND allocation_unit_id = (SELECT a.allocation_unit_id
                                 FROM   tempdb.sys.partitions AS p
                               INNER JOIN tempdb.sys.system_internals_allocation_units AS a
                                          ON p.hobt_id = a.container_id
                                        INNER JOIN tempdb.sys.columns AS c
                                          ON c.object_id = p.object_id
                                 WHERE  c.name = 'dba.se')
GROUP  BY is_modified 

ফলাফল

is_modified page_count
----------- -----------
0           192
1           61

দেখানো হচ্ছে যে 192 পৃষ্ঠাগুলি ডিস্কে লেখা ছিল এবং নোংরা পতাকা সাফ করা হয়েছে। এটি ডিস্কে লিখিত হওয়ার অর্থ এই নয় যে পৃষ্ঠাগুলি তত্ক্ষণাত বাফার পুল থেকে উচ্ছেদ করা হবে। এই টেবিল ভেরিয়েবলের বিপরীতে অনুসন্ধানগুলি এখনও মেমরি থেকে পুরোপুরি সন্তুষ্ট হতে পারে।

বাফার পুল পৃষ্ঠাগুলিতে max server memoryসেট করা 2000 MBএবং DBCC MEMORYSTATUSরিপোর্ট করা সহ একটি নিষ্ক্রিয় সার্ভারে প্রায় 1,843,000 কেবি (সি। 23,000 পৃষ্ঠাগুলি) হিসাবে বরাদ্দ করা হয়েছে আমি উপরে 1000 সারি / পৃষ্ঠাগুলির ব্যাচগুলিতে সারণি এবং প্রতিটি পুনরাবৃত্তির জন্য রেকর্ড করেছি।

SELECT Count(*)
FROM   sys.dm_os_buffer_descriptors
WHERE  database_id = 2
       AND allocation_unit_id = @allocId
       AND page_type = 'DATA_PAGE' 

টেবিলের ভেরিয়েবল এবং টেবিল উভয়ই #tempপ্রায় অভিন্ন গ্রাফ দিয়েছিল এবং বাফার পুলটি পুরোপুরি মেকস করতে সক্ষম হয়েছিল যে বিন্দুতে পৌঁছানোর আগে যে তারা সম্পূর্ণরূপে মেমরিতে ছিল না তাই মেমরির কোনও নির্দিষ্ট সীমাবদ্ধতা নেই বলে মনে হচ্ছে না হয় গ্রাস করতে পারেন।

বাফার পুলের পৃষ্ঠাগুলি


আমি খুঁজে পেয়েছি যে এসকিউএল সার্ভার একটি সমতুল্য টেবিল ভেরিয়েবলের তুলনায় টেম্প টেবিলগুলি তৈরি করে (এমনকি ক্যাশিং সহ) আরও উল্লেখযোগ্যভাবে আরও ল্যাচগুলি অর্জন করে। আপনি ল্যাচ_অ্যাকওয়ার্ডড ডিবাগ এক্সই ব্যবহার করে এবং প্রায় 35 টি কলাম বা তার সাথে একটি সারণী তৈরি করে পরীক্ষা করতে পারেন। আমি 4 টি ল্যাচ নিতে টেবিলের পরিবর্তনশীল এবং প্রায় 70 টি ল্যাচ নিয়ে টেম্প টেবিলটি পেয়েছি।
জো ওবিশ ২

40

অধ্যয়নের চেয়ে কিছু বিশেষ অভিজ্ঞতার উপর ভিত্তি করে আমি আরও কয়েকটি বিষয় উল্লেখ করতে চাই are ডিবিএ হিসাবে, আমি খুব নতুন তাই দয়া করে যেখানে প্রয়োজন সেখানে আমাকে সংশোধন করুন।

  1. ডিফল্টরূপে # টেম্প টেবিলগুলি এসকিউএল সার্ভারের উদাহরণের ডিফল্ট কোলেশন ব্যবহার করে। সুতরাং অন্যথায় সুনির্দিষ্ট না করা পর্যন্ত আপনি # টেম্প টেবিল এবং ডাটাবেস টেবিলের মধ্যে মানগুলির তুলনা বা আপডেট করতে সমস্যা হতে চলেছেন, যদি মাস্টারডিবিতে ডাটাবেস থেকে আলাদা কোলেশন থাকে। দেখুন: http://www.mssqltips.com/sqlservertip/2440/create-sql-server-temporary-tables-with-the-cor درست-collation/
  2. সম্পূর্ণরূপে ব্যক্তিগত অভিজ্ঞতার উপর ভিত্তি করে, উপলব্ধ মেমরির একটি প্রভাব রয়েছে যা আরও ভাল সম্পাদন করে। এমএসডিএন ছোট রেজাল্ট সেটগুলি সংরক্ষণের জন্য টেবিল ভেরিয়েবলগুলি ব্যবহারের পরামর্শ দেয় তবে বেশিরভাগ সময় পার্থক্যটি এমনকি লক্ষণীয় হয় না। বৃহত্তর সেটগুলিতে তবে এটি কিছু ক্ষেত্রে স্পষ্ট হয়ে উঠেছে যে টেবিলের ভেরিয়েবলগুলি অনেক বেশি মেমরির নিবিড় এবং ক্রোয়েটিকে ক্রল থেকে নামিয়ে আনা করতে পারে।

6
এছাড়াও মনে রাখবেন যে # টিম্প টেবিলগুলিতে কোলেশন কলিং ডাটাবেসের কল্যাশনের উত্তরাধিকারী হতে পারে যদি আপনি এসকিউএল সার্ভার 2012 ব্যবহার করেন এবং ডাটাবেস থাকে।
অ্যারন বার্ট্র্যান্ড

ছোট বড় সেট বনাম জন্য # 2 ব্যাখ্যা stackoverflow.com/a/14465163/5224021
GibralterTop
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.