Hostující autor:Derik Hammer (@SQLHammer)
Aaron Bertrand nedávno blogoval o škodlivých, všudypřítomných mýtech o výkonu serveru SQL. Jako rozšíření této série blogů se chystám vyvrátit tento běžný mýtus:
Čtení návodu
Přešel jsem přímo ke zdroji a podíval jsem se na článek Books Online o tabulkách, který obsahuje proměnné tabulky. I když se článek zmiňuje o výhodách používání proměnných tabulky, fakt, že jsou 100% v paměti, nápadně chybí.
Chybějící kladné tvrzení však neznamená zápor. Od vydání tabulek OLTP v paměti je nyní v BOL mnohem více dokumentace pro zpracování v paměti. Zde jsem našel tento článek o zrychlení dočasné tabulky a proměnných tabulky pomocí optimalizace paměti.
Celý článek se točí kolem toho, jak zajistit, aby vaše dočasné objekty používaly funkci OLTP v paměti, a tady jsem našel souhlas, který jsem hledal.
"Tradiční proměnná tabulky představuje tabulku v databázi tempdb. Pro mnohem rychlejší výkon můžete paměťovou proměnnou optimalizovat."Proměnné tabulky nejsou konstrukce v paměti. Abyste mohli používat technologii in-memory, musíte explicitně definovat TYPE, který je optimalizován pro paměť, a použít tento TYPE k definování proměnné tabulky.
Dokažte to
Dokumentace je jedna věc, ale vidět ji na vlastní oči je věc druhá. Vím, že dočasné tabulky vytvářejí objekty v tempdb a zapisují data na disk. Nejprve vám ukážu, jak to vypadá u dočasných tabulek, a poté použiji stejnou metodu k ověření hypotézy, že proměnné tabulky fungují stejným způsobem.
Analýza záznamů protokolu
Tento dotaz spustí CHECKPOINT, aby mi poskytl čistý výchozí bod, a poté zobrazí počet záznamů protokolu a názvy transakcí, které v protokolu existují.
USE tempdb; GO CHECKPOINT; GO SELECT COUNT(*) [Count] FROM sys.fn_dblog (NULL, NULL); SELECT [Transaction Name] FROM sys.fn_dblog (NULL, NULL) WHERE [Transaction Name] IS NOT NULL;
Opakované spouštění T-SQL vedlo ke konzistentnímu počtu tří záznamů na SQL Server 2016 SP1.
Tím se vytvoří dočasná tabulka a zobrazí se záznam objektu, což dokazuje, že se jedná o skutečný objekt v databázi tempdb.
USE tempdb; GO DROP TABLE IF EXISTS #tmp; GO CREATE TABLE #tmp (id int NULL); SELECT name FROM sys.objects o WHERE is_ms_shipped = 0;
Nyní znovu ukážu záznamy protokolu. Nebudu znovu spouštět příkaz CHECKPOINT.
Bylo zapsáno 21 záznamů protokolu, což dokazuje, že se jedná o zápisy na disk, a naše CREATE TABLE je v těchto záznamech jasně zahrnuta.
Abych porovnal tyto výsledky s proměnnými tabulky, resetuji experiment spuštěním CHECKPOINT a následným spuštěním T-SQL níže, čímž vytvořím proměnnou tabulky.
USE tempdb; GO DECLARE @var TABLE (id int NULL); SELECT name FROM sys.objects o WHERE is_ms_shipped = 0;
Opět tu máme nový objektový záznam. Tentokrát je však název náhodnější než u dočasných tabulek.
Existuje 82 nových záznamů protokolu a názvů transakcí, které dokazují, že moje proměnná se zapisuje do protokolu, a tedy na disk.
Ve skutečnosti v paměti
Nyní je čas, abych nechal záznamy protokolu zmizet.
Vytvořil jsem skupinu souborů OLTP v paměti a poté vytvořil typ tabulky optimalizované pro paměť.
USE Test; GO CREATE TYPE dbo.inMemoryTableType AS TABLE ( id INT NULL INDEX ix1 ) WITH (MEMORY_OPTIMIZED = ON); GO
Znovu jsem provedl CHECKPOINT a poté vytvořil tabulku optimalizovanou pro paměť.
USE Test; GO DECLARE @var dbo.inMemoryTableType; INSERT INTO @var (id) VALUES (1) SELECT * from @var; GO
Po kontrole protokolu jsem neviděl žádnou aktivitu protokolu. Tato metoda je ve skutečnosti 100% in-memory.
Odnést
Proměnné tabulky používají tempdb podobně jako dočasné tabulky používají tempdb. Proměnné tabulky nejsou konstrukcemi v paměti, ale mohou se jimi stát, pokud používáte uživatelsky definované typy tabulek optimalizované pro paměť. Často považuji dočasné tabulky za mnohem lepší volbu než proměnné tabulky. Hlavním důvodem je to, že proměnné tabulky nemají statistiku a v závislosti na verzi a nastavení serveru SQL Server odhady řádků vycházejí na 1 řádek nebo 100 řádků. V obou případech se jedná o dohady a stávají se škodlivými dezinformacemi v procesu optimalizace dotazů.
Všimněte si, že některé z těchto rozdílů ve funkcích se mohou časem změnit – například v posledních verzích SQL Server můžete vytvořit další indexy pro proměnnou tabulky pomocí inline syntaxe indexu. Následující tabulka má tři indexy; primární klíč (ve výchozím nastavení seskupený do klastrů) a dva indexy bez klastrů:
DECLARE @t TABLE ( a int PRIMARY KEY, b int, INDEX x (b, a DESC), INDEX y (b DESC, a) );
Na DBA Stack Exchange existuje skvělá odpověď, kde Martin Smith vyčerpávajícím způsobem popisuje rozdíly mezi proměnnými tabulky a #temp tabulkami:
- Jaký je rozdíl mezi dočasnou tabulkou a proměnnou tabulky na serveru SQL?