Vytvoření tabulky je operace poměrně náročná na zdroje a čas. Server musí najít a přidělit úložný prostor pro nová data a struktury indexu a provést odpovídající záznamy ve více tabulkách systémových metadat. Veškerá tato práce musí být provedena způsoby, které budou vždy správně fungovat při vysoké souběžnosti a které splňují všechny záruky ACID očekávané od relační databáze.
V SQL Server to znamená použít správné druhy zámků a západek ve správném pořadí a zároveň zajistit, aby podrobné záznamy protokolu transakcí byly bezpečně uloženy do trvalého úložiště ještě před jakýmikoli fyzickými změnami v databázi. Tyto záznamy protokolu zajišťují, že systém může vrátit databázi zpět do konzistentního stavu v případě vrácení transakce nebo selhání systému.
Svržení stolu je podobně nákladná operace. Naštěstí většina databází nevytváří ani nezahazuje tabulky s velkou frekvencí. Zjevnou výjimkou je systémová databáze tempdb . Tato jediná databáze obsahuje fyzické úložiště, alokační struktury, systémová metadata a záznamy protokolu transakcí pro všechny dočasné tabulky a proměnné tabulky v celé instanci SQL Serveru.
Přirozenou povahou dočasných tabulek a proměnných tabulek je vytváření a odstraňování mnohem častěji než jiné typy databázových objektů. Když se tato přirozeně vysoká frekvence vytváření a ničení zkombinuje s koncentračním účinkem všech dočasných tabulek a proměnných tabulek spojených s jedinou databází, není divu, že může dojít ke sporům v alokačních a metadatových strukturách tempdb databáze.
Dočasné ukládání objektů do mezipaměti
Chcete-li snížit dopad na tempdb struktur, může SQL Server ukládat dočasné objekty do mezipaměti pro opětovné použití. Namísto vypuštění dočasného objektu zachová SQL Server systémová metadata a zkrátí data tabulky. Pokud je velikost tabulky 8 MB nebo menší, zkrácení se provádí synchronně; jinak se používá odložená kapka. V obou případech zkrácení snižuje požadavky na úložiště na jednu (prázdnou) datovou stránku a informace o přidělení na jedinou stránku IAM.
Ukládání do mezipaměti se příště vyhne téměř všem nákladům na alokaci a metadata na vytvoření dočasného objektu. Jako vedlejší účinek menšího počtu změn v tempdb databáze než úplný cyklus zahození a opětovného vytvoření, dočasné ukládání objektů do mezipaměti také snižuje množství potřebného protokolování transakcí.
Dosažení ukládání do mezipaměti
Proměnné tabulky a místní dočasné tabulky lze uložit do mezipaměti. Chcete-li se kvalifikovat pro ukládání do mezipaměti, místní dočasná tabulka nebo proměnná tabulky musí být vytvořen v modulu:
- Uložená procedura (včetně dočasně uložené procedury)
- Spouštěč
- Funkce s tabulkovou hodnotou s více příkazy
- Skalární uživatelsky definovaná funkce
Vrácená hodnota funkce s tabulkovou hodnotou s více příkazy je proměnná tabulky, která může být sama uložena v mezipaměti. Parametry s hodnotou tabulky (což jsou také proměnné tabulky) lze uložit do mezipaměti, když je parametr odeslán z klientské aplikace, například v kódu .NET pomocí SqlDbType.Structured
. Když je příkaz parametrizován, struktury parametrů s hodnotou tabulky lze uložit do mezipaměti pouze na serveru SQL Server 2012 nebo novějším.
Následující nelze být uložen do mezipaměti:
- Globální dočasné tabulky
- Objekty vytvořené pomocí ad-hoc SQL
- Objekty vytvořené pomocí dynamického SQL (např. pomocí
EXECUTE
nebosys.sp_executesql
)
Aby byl dočasný objekt uložen do mezipaměti, navíc nesmí :
- Pojmenovali jste omezení (omezení bez explicitních jmen jsou naprosto v pořádku)
- Po vytvoření objektu proveďte "DDL".
- Být v modulu definovaném pomocí
WITH RECOMPILE
volba - Být volán pomocí
WITH RECOMPILE
možnostEXECUTE
prohlášení
Chcete-li explicitně vyřešit některé běžné mylné představy:
TRUNCATE TABLE
není zabránit ukládání do mezipamětiDROP TABLE
není zabránit ukládání do mezipamětiUPDATE STATISTICS
není zabránit ukládání do mezipaměti- Automatické vytváření statistik nevytváří zabránit ukládání do mezipaměti
- Ruční
CREATE STATISTICS
bude zabránit ukládání do mezipaměti
Všechny dočasné objekty v modulu jsou posuzovány z hlediska vhodnosti ukládání do mezipaměti samostatně. Modul, který obsahuje jeden nebo více dočasných objektů, které nelze uložit do mezipaměti, může stále splňovat podmínky pro ukládání dalších dočasných objektů v rámci stejného modulu.
Běžným vzorem, který zakazuje ukládání do mezipaměti pro dočasné tabulky, je vytváření indexů po úvodním příkazu k vytvoření tabulky. Ve většině případů to lze obejít pomocí primárního klíče a jedinečných omezení. V SQL Server 2014 a novějších máme možnost přidat nejedinečné neklastrované indexy přímo do příkazu pro vytvoření tabulky pomocí INDEX
doložka.
Monitorování a údržba
Můžeme vidět, kolik dočasných objektů je aktuálně uloženo v mezipaměti pomocí čítačů mezipaměti DMV:
SELECT DOMCC.[type], DOMCC.pages_kb, DOMCC.pages_in_use_kb, DOMCC.entries_count, DOMCC.entries_in_use_countFROM sys.dm_os_memory_cache_counters JAKO DOMCC KDE DOMCC.[name] =N'Temporary Table Variable Tables';>Příklad výsledku je:
Záznam mezipaměti je považován za použitý tak dlouho, dokud je vykonávána jakákoli část obsahujícího modulu. Souběžné spouštění stejného modulu povede k vytvoření více dočasných objektů uložených v mezipaměti. Více plánů provádění pro stejný modul (možná kvůli odlišné relaci
SET
options) také povede k více záznamům mezipaměti pro stejný modul.Záznamy mezipaměti mohou být časem zastaralé v reakci na konkurenční potřeby paměti. Dočasné objekty uložené v mezipaměti lze také odstranit (asynchronně, pomocí systémového vlákna na pozadí), když je z mezipaměti plánu odebrán plán provádění nadřazeného modulu.
Ačkoli to není podporováno (ani žádným způsobem doporučeno) pro produkční systémy, dočasné úložiště mezipaměti objektů lze pro účely testování ručně zcela vymazat pomocí:
DBCC FREESYSTEMCACHE('Dočasné tabulky a proměnné tabulky') S MARK_IN_USE_FOR_REMOVAL;WAITFOR DELAY '00:00:05';Pětisekundové zpoždění umožňuje spuštění úlohy čištění pozadí. Upozorňujeme, že tento příkaz je ve skutečnosti nebezpečný . Měli byste jej použít pouze (na vlastní riziko) v testovací instanci, ke které máte výhradní přístup. Po dokončení testování restartujte instanci SQL Server.
Podrobnosti implementace ukládání do mezipaměti
Proměnné tabulky jsou implementovány 'skutečnou' uživatelskou tabulkou v tempdb databáze (ačkoli nejde o tabulku, kterou můžeme dotazovat přímo). Název přidružené tabulky je "#" následovaný osmimístnou hexadecimální reprezentací ID objektu. Následující dotaz ukazuje vztah:
-- Proměnná tabulkyDECLARE @Z AS tabulka (z celé číslo NULL); -- Odpovídající položka sys.tablesSELECT T.[jméno], ObjIDFromName =CONVERT(celé číslo, CONVERT(binární(4), RIGHT(T.[jméno], 8), 2)), T.[id_objektu], T.[[ type_desc], T.create_date, T.modify_dateFROM tempdb.sys.tables AS T WHERE T.[name] LIKE N'#[0-9A-F][0-9A-F][0-9A-F][0 -9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]';Ukázkový výsledek je uveden níže. Všimněte si, jak se ID objektu vypočítané z názvu objektu shoduje se skutečným ID objektu:
Spuštění tohoto skriptu jako ad-hoc SQL vytvoří jinou tempdb ID objektu (a název objektu) při každém spuštění (bez ukládání do mezipaměti). Umístění stejného skriptu do modulu (např. uložené procedury) umožní ukládání proměnné tabulky do mezipaměti (pokud se nepoužívá dynamické SQL), takže ID a název objektu budou při každém spuštění stejné.
Když proměnná tabulky není uložena do mezipaměti, podkladová tabulka se pokaždé vytvoří a zruší. Když je povoleno dočasné ukládání objektů do mezipaměti, tabulka je na konci modulu zkrácena, místo aby byla zrušena. Nejsou žádné změny na systémová metadata, když je proměnná tabulky uložena do mezipaměti. Dopad na alokační struktury a protokolování transakcí je omezen na smazání řádků v tabulce a odstranění všech nadbytečných dat a alokačních stránek, když modul skončí.
Dočasné tabulky
Když se místo proměnné tabulky použije dočasná tabulka, základní mechanismus je v podstatě stejný, jen s několika dalšími kroky přejmenování:Když dočasná tabulka není uložena v mezipaměti , je vidět v tempdb se známým jménem dodaným uživatelem, za nímž následuje hromada podtržítek a hexadecimální reprezentace ID objektu jako konečná přípona. Místní dočasná tabulka zůstává, dokud není explicitně zrušena nebo dokud neskončí rozsah, ve kterém byla vytvořena. Pro ad-hoc SQL to znamená, když se relace odpojí od serveru.
Pro dočasnou tabulku uloženou v mezipaměti , při prvním spuštění modulu se dočasná tabulka vytvoří stejně jako pro případ bez mezipaměti. Na konci modulu je dočasná tabulka namísto automatického vypuštění (jak končí rozsah, ve kterém byla vytvořena) oříznuta a poté přejmenována na hexadecimální reprezentaci ID objektu (přesně jak je vidět u proměnné tabulky). Při příštím spuštění modulu se tabulka uložená v mezipaměti přejmenuje z hexadecimálního formátu na název zadaný uživatelem (plus podtržítka plus id hex objektu).
Další operace přejmenování na začátku a na konci modulu zahrnují malý počet systémových změn metadat . U dočasných tabulek uložených v mezipaměti se proto mohou stále vyskytovat spory o metadata při velmi vysoké míře opětovného použití. Dopad na metadata dočasné tabulky uložené v mezipaměti je však mnohem nižší než u případu bez mezipaměti (pokaždé vytvoření a odstranění tabulky).
Další podrobnosti a příklady toho, jak funguje dočasné ukládání objektů do mezipaměti, naleznete v mém předchozím článku.
Statistiky dočasných tabulek uložených v mezipaměti
Jak již bylo zmíněno, statistiky mohou být automaticky vytvořené na dočasných tabulkách bez ztráty výhod dočasného ukládání objektů do mezipaměti (připomínáme, že ruční vytváření statistik bude zakázat ukládání do mezipaměti).
Důležitým upozorněním je, že statistiky přidružené k dočasné tabulce uložené v mezipaměti nejsou resetovány když je objekt uložen do mezipaměti na konci modulu nebo když je objekt uložený v mezipaměti načten z mezipaměti na začátku modulu. V důsledku toho může statistika dočasné tabulky uložené v mezipaměti zůstat z nesouvisejícího předchozího spuštění. Jinými slovy, statistika nemusí mít absolutně žádnou souvislost na aktuální obsah dočasné tabulky.
To je samozřejmě nežádoucí vzhledem k tomu, že hlavním důvodem upřednostňování lokální dočasné tabulky před proměnnou tabulky je dostupnost přesné distribuční statistiky. V rámci zmírnění budou statistiky automaticky aktualizovány, když (pokud) akumulovaný počet změn v podkladovém objektu v mezipaměti dosáhne vnitřního prahu rekompilace. To je těžké předem posoudit, protože podrobnosti jsou složité a poněkud kontraintuitivní.
Nejkomplexnějším řešením při zachování výhod dočasného ukládání objektů do mezipaměti je:
- Ručně
UPDATE STATISTICS
na dočasné tabulce v rámci modulu; a - Přidejte
OPTION (RECOMPILE)
nápověda k příkazům, které odkazují na dočasnou tabulku
Přirozeně jsou s tím spojeny náklady, ale většinou je to přijatelné. Když se autor modulu rozhodl použít nejprve místní dočasnou tabulku, implicitně říká, že výběr plánu bude pravděpodobně citlivý na obsah dočasné tabulky, takže rekompilace může mít smysl. Ruční aktualizace statistik zajišťuje, že statistiky použité během rekompilace odrážejí aktuální obsah tabulky (jak bychom jistě očekávali).
Další podrobnosti o tom, jak to přesně funguje, najdete v mém předchozím článku na toto téma.
Shrnutí a doporučení
Dočasné ukládání objektů do mezipaměti v rámci modulu může výrazně snížit tlak na sdílenou alokaci a struktury metadat v tempdb databáze. K největšímu snížení dojde při použití proměnných tabulky, protože ukládání do mezipaměti a opětovné použití těchto dočasných objektů vůbec nezahrnuje úpravu metadat (žádné operace přejmenování). Spor o alokační struktury může být stále patrný, pokud jediná datová stránka uložená v mezipaměti nestačí k tomu, aby za běhu podržela všechna data proměnné tabulky.
Dopad na kvalitu plánu kvůli nedostatku informací o mohutnosti pro proměnné tabulky lze zmírnit použitím OPTION(RECOMPILE)
nebo příznak trasování 2453 (k dispozici od SQL Server 2012 a novější). Všimněte si, že tato omezení poskytují optimalizátoru pouze informace o celkovém počtu řádků v tabulce.
Pro zobecnění tabulkové proměnné nejlépe se používají, když jsou data malá (ideálně se vejdou na jednu datovou stránku pro maximální přínos sporu) a když výběr plánu nezávisí na hodnotách přítomných v proměnné tabulky.
Pokud informace o distribuci dat (hustota a histogramy) je důležitá pro výběr plánu, použijte místní dočasnou tabulku namísto. Ujistěte se, že splňujete podmínky pro dočasné ukládání tabulek do mezipaměti, což nejčastěji znamená nevytváření indexů nebo statistik po úvodním příkazu k vytvoření tabulky. To je od SQL Server 2014 pohodlnější díky zavedení INDEX
klauzule CREATE TABLE
prohlášení.
Explicitní UPDATE STATISTICS
po načtení dat do dočasné tabulky a OPTION (RECOMPILE)
tipy na příkazy, které odkazují na tabulku, mohou být potřebné k vytvoření všech očekávaných výhod dočasných tabulek uložených v mezipaměti v rámci modulu.
Je důležité používat dočasné objekty pouze tehdy, když přinášejí jasný přínos, nejčastěji z hlediska kvality plánu. Nadměrné, neefektivní nebo zbytečné používání dočasných objektů může vést k tempdb spor, i když je dosaženo dočasného ukládání objektů do mezipaměti.
Optimální dočasné ukládání objektů do mezipaměti nemusí stačit ke snížení tempdb spor o přijatelnou úroveň ve všech případech, i když se dočasné objekty používají pouze tehdy, jsou-li plně odůvodněné. Použití proměnných tabulek v paměti nebo neodolných tabulek v paměti může v takových případech poskytnout cílená řešení, i když vždy je třeba udělat kompromisy a žádné jediné řešení v současnosti nepředstavuje nejlepší možnost ve všech případech.