SQL සේවාදායකයේ තාවකාලික වගුවක් සහ වගු විචල්‍යය අතර වෙනස කුමක්ද?


459

මෙය මිථ්‍යාවන් කිහිපයක් හා පරස්පර අදහස් ඇති ප්‍රදේශයක් ලෙස පෙනේ.

ඉතින් SQL සේවාදායකයේ වගු විචල්‍යයක් සහ දේශීය තාවකාලික වගුවක් අතර වෙනස කුමක්ද?


Answers:


682

අන්තර්ගතය

අන්තර්ගතය

අවවාදය

මෙම පිළිතුර SQL සේවාදායක 2000 හි හඳුන්වා දුන් "සම්භාව්‍ය" වගු විචල්‍යයන් සාකච්ඡා කරයි. SQL සේවාදායකය 2014 මතකයේ OLTP විසින් මතක ප්‍රශස්ත වගු වර්ග හඳුන්වා දෙයි. පහත වගු වලට වඩා වගු විචල්‍ය අවස්ථා බොහෝ ආකාරවලින් වෙනස් වේ! ( වැඩි විස්තර ).

ගබඩා ස්ථානය

වෙනසක් නැත. දෙකම ගබඩා කර ඇත tempdb.

වගු විචල්‍යයන් සඳහා මෙය සැමවිටම එසේ නොවන නමුත් පහත සිට මෙය සත්‍යාපනය කළ හැකි බව මම යෝජනා කර ඇත්තෙමි

DECLARE @T TABLE(X INT)

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

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

උදාහරණ ප්‍රති Results ල ( tempdbපේළි 2 හි පිහිටීම පෙන්වයි )

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

තාර්කික පිහිටීම

@table_variables#tempවගු වලට වඩා වර්තමාන දත්ත ගබඩාවේ කොටසක් ලෙස හැසිරෙන්න . වගු විචල්‍යයන් සඳහා (2005 සිට) තීරු සංයුක්තයන් නිශ්චිතව දක්වා නොමැති නම් වත්මන් දත්ත සමුදායට සමාන වන අතර #tempවගු සඳහා එය පෙරනිමි එකතුව tempdb( වැඩි විස්තර ) භාවිතා කරයි. මීට අමතරව පරිශීලක අර්ථ දක්වන ලද දත්ත වර්ග සහ එක්ස්එම්එල් එකතු කිරීම් #tempවගු සඳහා භාවිතා කිරීමට තාවකාලික විය යුතු නමුත් වගු විචල්‍යයන්ට ඒවා වර්තමාන දත්ත ගබඩාවෙන් භාවිතා කළ හැකිය ( මූලාශ්‍රය ) .

SQL Server 2012 අඩංගු දත්ත සමුදායන් හඳුන්වා දෙයි. මේවායේ තාවකාලික වගු වල හැසිරීම වෙනස් වේ (h / t ආරොන්)

අඩංගු දත්ත ගබඩාවක තාවකාලික වගු දත්ත අඩංගු දත්ත ගබඩාවේ එකතුවෙහි සංයුක්ත වේ.

  • තාවකාලික වගු හා සම්බන්ධ සියලුම පාර-දත්ත (නිදසුනක් ලෙස, වගු සහ තීරු නම්, දර්ශක සහ යනාදිය) නාමාවලි එකතුවෙහි ඇත.
  • තාවකාලික වගු වල නම් කරන ලද සීමාවන් භාවිතා නොකෙරේ.
  • තාවකාලික වගු මඟින් පරිශීලක-නිර්වචනය කරන ලද වර්ග, XML යෝජනා ක්‍රම එකතු කිරීම හෝ පරිශීලක අර්ථ දක්වන ලද කාර්යයන් වෙත යොමු නොවිය හැකිය.

විවිධ විෂය පථයන්ට දෘශ්‍යතාව

@table_variablesප්‍රවේශ විය හැක්කේ ඒවා ප්‍රකාශයට පත් කරන ලද කණ්ඩායම හා විෂය පථය තුළ පමණි. #temp_tablesළමා කණ්ඩායම් තුළ ප්‍රවේශ විය හැකිය (කැදැලි ප්‍රේරක, ක්‍රියා පටිපාටිය, execඇමතුම්). #temp_tables( @@NESTLEVEL=0) පිටත විෂය පථයෙන් සාදන ලද ( ) සැසිය අවසන් වන තෙක්ම පවතින බැවින් කණ්ඩායම් ද විහිදේ. වත් වස්තුව වර්ගය ඊළඟ සාකච්ඡා කෙසේ වෙතත් ලෙස (ගෝලීය ළමා කණ්ඩායම නිර්මාණය හා ඉල්ලා විෂය පථය තුල ලබා ගත හැකි බව ##tempවගු හැකි වුවත් විය).

ජීවිත කාලය

@table_variablesDECLARE @.. TABLEප්‍රකාශයක් අඩංගු කණ්ඩායමක් ක්‍රියාත්මක වන විට (එම කණ්ඩායමේ ඕනෑම පරිශීලක කේතයක් ක්‍රියාත්මක වීමට පෙර) ව්‍යංගයෙන් නිර්මාණය වන අතර අවසානයේ එය ව්‍යංගයෙන් අතහැර දමනු ලැබේ.

DECLAREප්‍රකාශයට පෙර වගු විචල්‍යය උත්සාහ කිරීමට සහ භාවිතා කිරීමට විග්‍රහකයා ඔබට ඉඩ නොදුනද , ව්‍යංග නිර්මාණය පහත දැක්වේ.

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

--Works fine
SELECT *
FROM @T

#temp_tablesTSQL CREATE TABLEප්‍රකාශය හමු වූ විට පැහැදිලිවම නිර්මාණය කර ඇති අතර එය පැහැදිලිවම අතහැර දැමිය හැකිය. DROP TABLEනැතහොත් කණ්ඩායම අවසන් වූ විට (ළමා කණ්ඩායමක් සමඟ නිර්මාණය කර ඇත්නම් @@NESTLEVEL > 0) හෝ සැසිය වෙනත් ආකාරයකින් අවසන් වූ විට ව්‍යංගයෙන් ඉවත් වේ.

සැ.යු: නව වගු නැවත නැවත නිර්මාණය කිරීම හා අතහැර දැමීම වෙනුවට ගබඩා කළ ක්‍රියාකාරකම් තුළ වස්තු වර්ග දෙකම හැඹිලිගත කළ හැකිය . කෙසේ වෙතත් මෙම හැඹිලිය සිදුවිය හැක්කේ කවදාද යන්න උල්ලං to නය කළ හැකි නමුත් කෙසේ හෝ වළක්වාලීමේ #temp_tablesසීමාවන් තිබේ @table_variables. හැඹිලිගත කිරීම සඳහා නඩත්තු පොදු කාර්ය #tempවගු වේ තරමක් වගුව විචල්යයන් සඳහා වඩා වැඩි මෙහි රූප සටහනෙහි දැක්වෙන පරිදි .

වස්තු පාර-දත්ත

වස්තු වර්ග දෙකටම මෙය අත්‍යවශ්‍යයෙන්ම සමාන වේ. එය පද්ධති පාදක වගු තුළ ගබඩා කර ඇත tempdb. පද්ධති වගු තුළට යතුර භාවිතා කළ හැකි පරිදි #tempවගුවක් බැලීම වඩාත් සරල වන OBJECT_ID('tempdb..#T')අතර අභ්‍යන්තරව ජනනය කරන ලද නම CREATE TABLEප්‍රකාශයේ අර්ථ දක්වා ඇති නම සමඟ වඩා සමීපව සම්බන්ධ වේ. වගු විචල්‍යයන් සඳහා object_idශ්‍රිතය ක්‍රියා නොකරන අතර අභ්‍යන්තර නාමය මුළුමනින්ම විචල්‍ය පද්ධතියට කිසිදු සම්බන්ධයක් නොමැතිව ජනනය වේ. පහත දැක්වෙන්නේ පාරදත්ත තවමත් පවතින බව (කෙසේ වෙතත් අද්විතීය) තීරු නාමයක් යතුරු කිරීමෙන් ය. අද්විතීය තීරු නම් නොමැති වගු සඳහා, 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 . පොදු වැරදි වැටහීමක් නම් මෙය වගු විචල්‍යයන් සඳහා නොවන බැවින් මෙය පෙන්වන ස්ක්‍රිප්ටයක් පහතින්, එය වගු විචල්‍යයක් ප්‍රකාශ කරයි, පේළි කිහිපයක් එකතු කර ඒවා යාවත්කාලීන කර මකා දමයි.

වගු විචල්‍යය ආරම්භයේ සහ අවසානයේ ව්‍යංගයෙන් නිර්මාණය කර ඇති අතර සම්පූර්ණ ල ging ු-සටහන බැලීමට බහු කණ්ඩායම් භාවිතා කිරීම අවශ්‍ය වේ.

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 

ප්‍රතිලාභ

සවිස්තරාත්මක දැක්ම

ප්‍රති .ලවල තිර රුව

සාරාංශ දර්ශනය (ව්‍යංග බිංදුව සහ පද්ධති පාදක වගු සඳහා ලොග් වීම ඇතුළත් වේ)

ප්‍රති .ලවල තිර රුව

දෙකෙහිම මෙහෙයුම් හඳුනා ගැනීමට මට හැකි තාක් දුරට දළ වශයෙන් සමාන ල ging ු-සටහන් ජනනය කරයි.

ක්රයාත්මක ප්රමාණය සටහන් කිරීම ඉතා සමාන වේ එක් වැදගත් වෙනසක් කිරීම හා සම්බන්ධ වන බව සටහන වාර්තා වේ #tempයම් අවස්ථාවක දී ලියන බව වගු එසේ දිගු ගනුදෙනුව කිසිදු අඩංගු පරිශීලක ගනුදෙනුව කරලා ඉවර වුණාට තෙක් සිදු එළි පෙහෙළි කළ නොහැකි #tempඅතර වගු සටහන කවලම් වැළැක්වීම ඇත tempdbස්වතන්ත්ර ගනුදෙනු ෙහයින්ද, වගු විචල්‍යයන් සඳහා විහිදුණු ඒවා නැත.

වගු විචල්‍යයන් සහය නොදක්වන TRUNCATEබැවින් වගුවකින් සියලු පේළි ඉවත් කිරීම අවශ්‍ය වන විට එය ලොග් වීමේ අවාසියක් විය හැකිය (ඉතා කුඩා වගු සඳහා DELETE කෙසේ හෝ වඩා හොඳින් ක්‍රියා කළ හැකි වුවද )

කාර්දිනල්

වගු විචල්‍යයන් සම්බන්ධ බොහෝ ක්‍රියාත්මක කිරීමේ සැලසුම් මඟින් ඒවායේ ප්‍රතිදානය ලෙස ඇස්තමේන්තු කර ඇති තනි පේළියක් පෙන්වනු ඇත. SQL Server මේසය විචල්ය ඇති බව විශ්වාස කරන බව මේසය විචල්ය ගුණ දර්ශන පරීක්ෂා ශුන්ය පේළි (එය 1 පේලිය ශුන්ය පේළිය වගුව මගින් විමෝචනය කරනු ඇත තක්සේරු ඇයි @Paul වයිට් විසින් විස්තර කර ඇත මෙහි ).

කෙසේ වෙතත් පෙර කොටසේ පෙන්වා ඇති ප්‍රති results ල තුළ නිවැරදි 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

විලම්බිත සම්පාදනයෙන් පසුව නිවැරදි ඇස්තමේන්තුගත පේළි ගණන සැලැස්මෙහි දැක්වේ.

නිවැරදි පේළි ගණන පෙන්වයි

SQL Server 2012 SP2 හි, ලුහු ce ු ධජය 2453 හඳුන්වා දී ඇත. වැඩි විස්තර මෙහි "සම්බන්ධතා එන්ජිම" යටතේ ඇත .

මෙම හෝඩුවාවේ ධජය සක්‍රිය කර ඇති විට, වැඩි කල් නොගොස් සාකච්ඡා කළ පරිදි ස්වයංක්‍රීයව නැවත සකස් කිරීම මගින් වෙනස් වූ කාර්දිනල් බව සැලකිල්ලට ගත හැකිය.

සැ.යු: අනුකූලතා මට්ටමේ අසුර් මත ප්‍රකාශය සම්පාදනය කිරීම පළමු ක්‍රියාත්මක වන තෙක් කල් දමා ඇත. මෙයින් අදහස් කරන්නේ එය තවදුරටත් ශුන්‍ය පේළි ඇස්තමේන්තු ගැටලුවට යටත් නොවන බවයි.

තීරු සංඛ්‍යාලේඛන නොමැත

වඩාත් නිවැරදි වගු කාර්දිනල්ත්වයක් තිබීම ඇස්තමේන්තුගත පේළි ගණන කෙසේ වෙතත් වඩාත් නිවැරදි වනු ඇතැයි අදහස් නොකෙරේ (වගුවේ ඇති සියලුම පේළි වල මෙහෙයුමක් නොකරන්නේ නම්). SQL සේවාදායකය වගු විචල්‍යයන් සඳහා තීරු සංඛ්‍යාලේඛන කිසිසේත් නඩත්තු නොකරන අතර සංසන්දනය අනාවැකි මත පදනම්ව අනුමාන මතට වැටෙනු ඇත (උදා: වගුවේ 10% =අද්විතීය නොවන තීරුවකට එරෙහිව හෝ 30% >සංසන්දනයක් සඳහා ආපසු ලබා දෙනු ඇත ). ඊට වෙනස්ව තීරුව සංඛ්යා ලේඛන වේ සඳහා පවත්වා #tempවගු.

SQL සේවාදායකය සෑම තීරුවකටම සිදුකරන ලද වෙනස් කිරීම් ගණන ගණනය කරයි. සැලැස්ම සම්පාදනය කළ දින සිට සිදුකරන ලද වෙනස් කිරීම් ගණන නැවත සකස් කිරීමේ සීමාව (RT) ඉක්මවා ගියහොත් සැලැස්ම නැවත සකස් කර සංඛ්‍යාලේඛන යාවත්කාලීන කරනු ලැබේ. RT වගු වර්ගය සහ ප්‍රමාණය මත රඳා පවතී.

සිට 2008 SQL Server ගැන සැලැස්ම කල ගබඩා කරන

RT පහත පරිදි ගණනය කෙරේ. (n යනු විමසුම් සැලැස්මක් සම්පාදනය කරන විට වගුවේ කාර්දිනල් භාවයයි.)

ස්ථිර වගුව
- n <= 500 නම්, RT = 500.
- n> 500 නම්, RT = 500 + 0.20 * n.

තාවකාලික වගුව
- n <6 නම්, RT = 6.
- 6 <= n <= 500 නම්, RT = 500.
- n> 500 නම්, RT = 500 + 0.20 * n.
වගු විචල්‍යය
- RT නොපවතී. එබැවින්, වගු විචල්‍යයන්ගේ කාර්දිනල්වල වෙනස්වීම් නිසා නැවත සකස් කිරීම් සිදු නොවේ. (නමුත් පහත TF 2453 පිළිබඳ සටහන බලන්න)

මෙම KEEP PLANඉඟියක් සඳහා RT සකස් කිරීම සඳහා භාවිතා කල හැක #tempස්ථිර වගු සඳහා මෙන් ම වගු.

මේ සියල්ලේ ශුද්ධ ප්‍රති is ලය නම්, බොහෝ විට #tempවගු සඳහා ජනනය කරන සැලසුම් ක්‍රියාත්මක කිරීම @table_variablesSQL සේවාදායකය සමඟ වැඩ කිරීමට වඩා හොඳ තොරතුරු ඇති බැවින් බොහෝ පේළි සම්බන්ධ වන විට වඩා විශාල ප්‍රමාණයේ ඇණවුම් වේ .

සැ.යු. අතිරේක එකක් නම් N=0 -> RT = 1. එනම් වගු විචල්‍යය හිස් වූ විට සම්පාදනය කරන ලද සියලුම ප්‍රකාශයන් නැවත සකස් කිරීමක් ලබා ගන්නා අතර TableCardinalityහිස් නොවන විට ඒවා ක්‍රියාත්මක කළ පළමු අවස්ථාව නිවැරදි කරනු ඇත. සම්පාදිත කාලසටහන් කාර්දිනල් භාවය සැලැස්ම තුළ ගබඩා කර ඇති අතර එම ප්‍රකාශය එකම කාර්දිනල්තාවයකින් නැවත ක්‍රියාත්මක කරන්නේ නම් (පාලන ප්‍රකාශයන් ගලායාම හෝ හැඹිලි සැලැස්මක් නැවත භාවිතා කිරීම නිසා) නැවත සකස් කිරීමක් සිදු නොවේ.

සැ.යු: ගබඩා කර ඇති ක්‍රියා පටිපාටිවල හැඹිලි තාවකාලික වගු සඳහා, නැවත විස්තර කිරීමේ කතාව ඉහත විස්තර කර ඇති ආකාරයට වඩා සංකීර්ණ ය. සියලු විස්තර සඳහා ගබඩා කළ පටිපාටිවල තාවකාලික වගු බලන්න .

නැවත සකස් කිරීම

ඉහත #tempවගු වල විස්තර කර ඇති වෙනස් කිරීම් මත පදනම් වූ ප්‍රතිනිර්මාණයන් අතිරේක සම්පාදකයන් සමඟ සම්බන්ධ කළ හැක්කේ ඒවා සම්පාදනයක් අවුලුවන වගු විචල්‍යයන් සඳහා තහනම් කර ඇති මෙහෙයුම් වලට ඉඩ දෙන බැවිනි (උදා: ඩීඩීඑල් වෙනස්කම් CREATE INDEX, ALTER TABLE)

අගුලු දැමීම

එය සඳහන් කර ඇත මේසය විචල්ය අගුළු සහභාගී නොවන බව. මෙය එසේ නොවේ. පහත දැක්වෙන ප්‍රතිදානයන් SSMS පණිවිඩ පටිත්ත වෙත ධාවනය කිරීමෙන් ඇතුළු කිරීමේ ප්‍රකාශයක් සඳහා ගෙන ඇති සහ මුදා හරින ලද අගුල් පිළිබඳ විස්තර.

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

වත් දර්ශකය ප්රධාන පිණිස මෙම නැවත ප්රතිඵල SQL Server සඳහා භාවිතා බව සඳහන් වෙන් ස්කෑන් නියෝග දෙකම සඳහා.

මම ඉහත පිටපත දෙවරක් ධාවනය කළ අතර දෙවන ධාවනය සඳහා ප්‍රති results ල පහතින්

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 

SQL සේවාදායකය විසින් වස්තුව මත ක්‍රමානුකූල ස්ථායිතා අගුලක් ලබා ගන්නා බැවින් වගු විචල්‍යය සඳහා අගුළු දැමීමේ ප්‍රතිදානය සැබවින්ම අවම වේ. නමුත් #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.

BEGIN TRAN ... ROLLBACKපේළි 26 ක් ආපසු හරවා යැවීමෙන් පෙන්වන්නේ වස්තුව මත සහ පද්ධති වගු පේළි දෙකෙහිම අගුල් රඳවා තබා ඇති බවයි. සමාන වගු විචල්‍ය ක්‍රියාකාරිත්වය පරිශීලක ගනුදෙනුව සමඟ පෙරළීමට යටත් නොවන අතර ඊළඟ ප්‍රකාශය පරීක්ෂා කිරීම සඳහා අපට මෙම අගුල් රඳවා තබා ගැනීමේ අවශ්‍යතාවයක් නොමැත, නමුත් ප්‍රොෆයිලර් තුළ අත්පත් කර ගෙන මුදා හරින ලද අගුල් සොයා ගැනීම හෝ හෝඩුවාව ධජය 1200 භාවිතා කිරීම මඟින් බොහෝ අගුලු දැමීමේ සිදුවීම් තවමත් සිදු වේ සිදු වේ.

දර්ශක

SQL Server 2014 ට පෙර සංස්කරණ සඳහා දර්ශක නිර්මාණය කළ හැක්කේ අද්විතීය බාධකයක් හෝ ප්‍රාථමික යතුරක් එක් කිරීමේ අතුරු as ලයක් ලෙස වගු විචල්‍යයන් මත පමණි. මෙයින් අදහස් කරන්නේ අද්විතීය දර්ශක පමණක් සහාය දක්වන බවයි. අද්විතීය පොකුරු දර්ශකයක් සහිත වගුවක අද්විතීය නොවන පොකුරු නොවන දර්ශකයක් කෙසේ වෙතත් එය සරලව ප්‍රකාශ කිරීමෙන් UNIQUE NONCLUSTEREDසහ අපේක්ෂිත NCI යතුරේ අවසානයට CI යතුර එක් කිරීමෙන් (SQL සේවාදායකය තිරය ​​පිටුපස මෙය සිදු කරයි. NCI නියම කළ හැකිය)

පෙන්නුම් පෙර විවිධ ලෙස index_optionගේ ඇතුළු අවහිරතා ප්රකාශ හි නිශ්චිතව දක්වා හැක DATA_COMPRESSION, IGNORE_DUP_KEYහා FILLFACTOR(එය පමණක් දර්ශකය මත යම් වෙනසක් නැවත ඉපයිය හැකි සහ ඔබ මේසය විචල්ය පිළිබඳ දර්ශක නැවත නො හැකි ලෙස එක සැකසීම පලක් නැති වුවද!)

මීට අමතරව වගු විචල්‍යයන් INCLUDEd තීරු, පෙරහන් කළ දර්ශක (2016 වන තෙක්) හෝ කොටස් කිරීම, #tempවගු ක්‍රියා නොකරයි (කොටස් යෝජනා ක්‍රමය නිර්මාණය කළ යුතුය tempdb).

SQL සේවාදායකයේ දර්ශක 2014

SQL සේවාදායක 2014 හි වගු විචල්‍ය අර්ථ දැක්වීමේදී අද්විතීය නොවන දර්ශක පේළිගත කළ හැකිය. මේ සඳහා උදාහරණ සින්ටැක්ස් පහතින්.

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*/
);

SQL සේවාදායකයේ දර්ශක 2016

CTP 3.1 සිට වගු විචල්යයන් සඳහා පෙරහන් කළ දර්ශක ප්රකාශයට පත් කළ හැකිය. සම්පත් අවහිරතා හේතුවෙන් ඒවා SQL16 බවට පත් නොකිරීමට ඉඩ ඇති නමුත් RTM මඟින් තීරු ඇතුළත් කිරීමට ඉඩ දී ඇත.

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පරිමාණ හෝ බහු ප්‍රකාශන වගු UDF තුළ භාවිතා කළ හැකිය.
  • @table_variables නම් කළ සීමාවන් තිබිය නොහැක.
  • @table_variablesකළ නොහැකි SELECT-ed INTO, ALTER-ed, TRUNCATEඈ හෝ ඉලක්ක විය හැක DBCCවැනි විධාන DBCC CHECKIDENTහෝ SET IDENTITY INSERTහා වැනි වගුව ඉඟි සපයන්නේ නැතWITH (FORCESCAN)
  • CHECK වගු විචල්‍යයන්හි සීමාවන් සරල කිරීම, ඇඟවුම් කළ අනාවැකි හෝ ප්‍රතිවිරෝධතා අනාවරණය කිරීම සඳහා ප්‍රශස්තකරණය විසින් නොසලකයි.
  • මේසය විචල්යයන් සඳහා සුදුසුකම් ලබා ගැනීමට අහිතක් නෑ rowset බෙදා ප්රශස්තිකරණය මෙම එරෙහිව delete කිරීම සහ යාවත්කාලීන සැලසුම් වැඩි පොදු කාර්ය මුහුණ හා හැකි බව අර්ථය PAGELATCH_EXබලා සිටියි. ( උදාහරණය )

මතකය පමණක්ද?

ආරම්භයේ සඳහන් කළ පරිදි දෙකම පිටු වල ගබඩා වේ tempdb. කෙසේ වෙතත් මෙම පිටු තැටියට ලිවීමේදී හැසිරීමේ වෙනසක් තිබේදැයි මම ආමන්ත්‍රණය නොකළෙමි.

මම මේ පිළිබඳව කුඩා පරිමාණයේ පරීක්ෂණයක් කර ඇති අතර මෙතෙක් එවැනි වෙනසක් දක්නට නොලැබුණි. SQL සේවාදායකයේ 250 පිටුව පිළිබඳ මගේ විශේෂිත පරීක්ෂණයකදී දත්ත ගොනුව ලිවීමට පෙර කපා හැරීමේ ලක්ෂ්‍යය ලෙස පෙනේ.

සැ.යු: පහත හැසිරීම තවදුරටත් SQL Server 2014 හෝ SQL Server 2012 SP1 / CU10 හෝ SP2 / CU1 හි සිදු නොවේ . උනන්දුවක් දක්වන ලේඛකයා තවදුරටත් තැටියට පිටු ලිවීමට උනන්දු නොවේ. SQL Server 2014 හි එම වෙනස පිළිබඳ වැඩි විස්තර : tempdb සැඟවුණු කාර්ය සාධනය මැණික් .

පහත පිටපත ධාවනය කිරීම

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ක්රියාවලිය අධීක්ෂණය මම දුටු කිසිවක් (පියවා 73.728 දී දත්ත ඇරඹුම් පිටුවට ඉඳහිට අය හැර) සමග දත්ත ගොනු. වෙනස් කල පසුව 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 KB (පිටු 23,000) ලෙස වෙන් කර ඇත. මම ඉහත වගු සඳහා පේළි / පිටු 1,000 බැගින් ඇතුළත් කර ඇති අතර එක් එක් පුනරාවර්තනය සඳහා.

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

මේස විචල්‍යය සහ වගුව යන දෙකම #tempඑක හා සමාන ප්‍රස්ථාර ලබා දී ඇති අතර ඒවා සම්පූර්ණයෙන්ම මතකයේ රඳවා නොතිබීමට පෙර බෆර් තටාකයෙන් උපරිම ප්‍රයෝජන ගැනීමට සමත් විය, එබැවින් මතකය කොපමණ දැයි නිශ්චිත සීමාවක් නොපෙනේ. එක්කෝ පරිභෝජනය කළ හැකිය.

ස්වාරක්ෂක තටාකයේ පිටු


සමාන වගු විචල්‍යයකට සාපේක්ෂව තාවකාලික වගු නිර්මාණය කිරීමේදී (හැඹිලි සහිතව වුවද) SQL සේවාදායකය සැලකිය යුතු ලෙස වැඩි අගයක් ලබා ගන්නා බව මම සොයා ගතිමි. ඔබට latch_acquired නිදොස් කිරීමේ XE භාවිතා කිරීමෙන් සහ තීරු 35 ක් හෝ ඊට වැඩි ප්‍රමාණයක් සහිත වගුවක් සෑදීමෙන් පරීක්ෂා කළ හැකිය. වැසිකිළි 4 ක් ගැනීමට මේස විචල්‍යය සහ අගුල් 70 ක් පමණ ගෙනයාමට තාවකාලික වගුව මට හමු විය.
ජෝ ඔබ්බිෂ්

41

අධ්‍යයනයට වඩා විශේෂිත අත්දැකීම් මත පදනම්ව මා පෙන්වා දීමට කැමති කරුණු කිහිපයක් තිබේ. ඩී.බී.ඒ ලෙස, මම ඉතා අළුත් බැවින් කරුණාකර අවශ්‍ය තැන මාව නිවැරදි කරන්න.

  1. පෙරනිමියෙන් #temp වගු SQL සේවාදායකයේ පෙරනිමි එකතුව භාවිතා කරයි. එබැවින් වෙනත් ආකාරයකින් නිශ්චිතව දක්වා නොමැති නම්, මාස්ටර්ඩීබයට දත්ත සමුදායෙන් වෙනස් එකතුවක් තිබේ නම්, # ටෙම්ප් වගු සහ දත්ත සමුදා වගු අතර අගයන් සංසන්දනය කිරීමේදී හෝ යාවත්කාලීන කිරීමේදී ඔබට ගැටළු ඇති විය හැකිය. බලන්න: http://www.mssqltips.com/sqlservertip/2440/create-sql-server-temporary-tables-with-the-correct-collation/
  2. පුද්ගලික අත්දැකීම් මත පදනම්ව, ලබා ගත හැකි මතකය වඩා හොඳින් ක්‍රියා කරන බලපෑමක් ඇති බව පෙනේ. කුඩා ප්‍රති result ල කට්ටල ගබඩා කිරීම සඳහා වගු විචල්‍යයන් භාවිතා කිරීමට MSDN නිර්දේශ කරයි, නමුත් බොහෝ විට වෙනස පවා නොපෙනේ. කෙසේවෙතත්, විශාල කට්ටල වලදී, වගු විචල්‍යයන් වඩා මතක ශක්තියකින් යුක්ත වන අතර විමසුම බඩගා යාමක් දක්වා මන්දගාමී විය හැකිය.

6
ඔබ SQL Server 2012 භාවිතා කරන අතර දත්ත සමුදාය අඩංගු නම් # ටෙම්ප් වගු වල එකතුවට ඇමතුම් දත්ත ගබඩාවේ එකතුව උරුම විය හැකි බව සලකන්න .
ආරොන් බර්ට්‍රන්ඩ්

කුඩා එදිරිව විශාල කට්ටල සඳහා # 2 හි පැහැදිලි කිරීම stackoverflow.com/a/14465163/5224021
සිත්ගන්නාසුළු-නම-මෙහි
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.