මෙය මිථ්යාවන් කිහිපයක් හා පරස්පර අදහස් ඇති ප්රදේශයක් ලෙස පෙනේ.
ඉතින් SQL සේවාදායකයේ වගු විචල්යයක් සහ දේශීය තාවකාලික වගුවක් අතර වෙනස කුමක්ද?
මෙය මිථ්යාවන් කිහිපයක් හා පරස්පර අදහස් ඇති ප්රදේශයක් ලෙස පෙනේ.
ඉතින් SQL සේවාදායකයේ වගු විචල්යයක් සහ දේශීය තාවකාලික වගුවක් අතර වෙනස කුමක්ද?
Answers:
අන්තර්ගතය
අවවාදය
මෙම පිළිතුර 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_variables
DECLARE @.. TABLE
ප්රකාශයක් අඩංගු කණ්ඩායමක් ක්රියාත්මක වන විට (එම කණ්ඩායමේ ඕනෑම පරිශීලක කේතයක් ක්රියාත්මක වීමට පෙර) ව්යංගයෙන් නිර්මාණය වන අතර අවසානයේ එය ව්යංගයෙන් අතහැර දමනු ලැබේ.
DECLARE
ප්රකාශයට පෙර වගු විචල්යය උත්සාහ කිරීමට සහ භාවිතා කිරීමට විග්රහකයා ඔබට ඉඩ නොදුනද , ව්යංග නිර්මාණය පහත දැක්වේ.
IF (1 = 0)
BEGIN
DECLARE @T TABLE(X INT)
END
--Works fine
SELECT *
FROM @T
#temp_tables
TSQL 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_variables
SQL සේවාදායකය සමඟ වැඩ කිරීමට වඩා හොඳ තොරතුරු ඇති බැවින් බොහෝ පේළි සම්බන්ධ වන විට වඩා විශාල ප්රමාණයේ ඇණවුම් වේ .
සැ.යු. අතිරේක එකක් නම් 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
(එය පමණක් දර්ශකය මත යම් වෙනසක් නැවත ඉපයිය හැකි සහ ඔබ මේසය විචල්ය පිළිබඳ දර්ශක නැවත නො හැකි ලෙස එක සැකසීම පලක් නැති වුවද!)
මීට අමතරව වගු විචල්යයන් INCLUDE
d තීරු, පෙරහන් කළ දර්ශක (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
වගු විචල්යයන්හි සීමාවන් සරල කිරීම, ඇඟවුම් කළ අනාවැකි හෝ ප්රතිවිරෝධතා අනාවරණය කිරීම සඳහා ප්රශස්තකරණය විසින් නොසලකයි.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
මම පහත ලෙස මෙසේ ලියයි බලන්න පටන්ගත්තා.
ඉහත තිර පිටුවේ පිටු 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
එක හා සමාන ප්රස්ථාර ලබා දී ඇති අතර ඒවා සම්පූර්ණයෙන්ම මතකයේ රඳවා නොතිබීමට පෙර බෆර් තටාකයෙන් උපරිම ප්රයෝජන ගැනීමට සමත් විය, එබැවින් මතකය කොපමණ දැයි නිශ්චිත සීමාවක් නොපෙනේ. එක්කෝ පරිභෝජනය කළ හැකිය.
අධ්යයනයට වඩා විශේෂිත අත්දැකීම් මත පදනම්ව මා පෙන්වා දීමට කැමති කරුණු කිහිපයක් තිබේ. ඩී.බී.ඒ ලෙස, මම ඉතා අළුත් බැවින් කරුණාකර අවශ්ය තැන මාව නිවැරදි කරන්න.