V tomto pokračování mé série „kolenního ladění výkonu“ bych rád probral čtyři běžné problémy, které vidím při používání dočasných tabulek. Každý z těchto problémů může ochromit pracovní zátěž, takže stojí za to o nich vědět a hledat je ve vašem prostředí.
Problém 1:Použití dočasných tabulek tam, kde nejsou potřeba
https://www.flickr. com/photos/tea_time/3890677277/Dočasné tabulky mají různá použití (pravděpodobně nejběžnějším je uložení mezivýsledkové sady pro pozdější použití), ale musíte si uvědomit, že když do dotazu vložíte dočasnou tabulku, přerušíte tok dat přes procesor dotazu.
Přemýšlejte o populaci dočasné tabulky jako o tvrdém zastavení, protože existuje dotaz (říkejme tomu producent) k vytvoření sady mezilehlých výsledků, která je pak uložena v dočasné tabulce v databázi tempdb, a pak další dotaz (nazvěme spotřebitel) musí znovu načíst data z dočasné tabulky.
Často jsem zjistil, že některé části pracovní zátěže ve skutečnosti fungují lépe, když je dočasná tabulka zcela odstraněna, takže data proudí z produkční části dotazu do spotřebitelské části dotazu, aniž by musela být uložena v tempdb, a optimalizátor dotazů může vytvořit optimálnější celkový plán.
Možná si teď říkáte:"Tak proč by někdo používal dočasný stůl, když to zpomaluje?" – a právem! V takových případech jsem zjistil, že používání dočasné tabulky se ve vývojovém týmu institucionalizovalo; někdo zjistil, že používání dočasné tabulky před mnoha lety zvýšilo výkon, takže se dočasné tabulky staly výchozí volbou návrhu.
To může být těžké změnit, zvláště pokud máte staršího vývojáře nebo manažera, který je přesvědčen, že dočasné tabulky by se měly vždy používat. Jednoduchá věc, kterou můžete vyzkoušet, je vybrat drahý dotaz (například dlouhotrvající dotaz nebo dotaz, který se provádí mnohokrát za sekundu) a odstranit jednu nebo více dočasných tabulek, abyste viděli, zda se výkon bez nich zvýší. A pokud ano, je tu váš důkaz, který ukáže neústupné!
Problém 2:Nedostatek filtrování při naplňování dočasných tabulek
I když nemůžete dočasnou tabulku odstranit, můžete být schopni výrazně zlepšit výkon tím, že se ujistíte, že kód, který naplňuje dočasnou tabulku, správně filtruje data získaná ze zdrojových tabulek.
Ztratil jsem počet, kolikrát jsem viděl, jak se dočasná tabulka naplňuje kódem, který začíná jako SELECT *
, obsahuje několik neomezených spojení a nemá klauzuli WHERE, a pak pozdější dotaz, který používá dočasnou tabulku, používá pouze několik sloupců a má klauzuli WHERE, která výrazně snižuje počet řádků.
Vzpomínám si na jeden případ, kdy dočasná tabulka v uložené proceduře shromažďovala data za 15 let z hlavní databáze a poté byla používána pouze data aktuálního roku. To opakovaně způsobovalo růst databáze tempdb, dokud jí nedošel prostor na disku a uložená procedura by selhala.
Kdykoli naplňujete dočasnou tabulku, používejte pouze sloupce zdrojové tabulky, které jsou nezbytné, a používejte pouze řádky, které jsou nezbytné – tj. posuňte predikáty filtru nahoru do kódu naplnění dočasné tabulky. Nejen, že to ušetří místo v tempdb, ale také ušetří spoustu času tím, že nebudete muset kopírovat nepotřebná data ze zdrojové tabulky (a potenciálně odstraní nutnost číst stránky zdrojové databáze z disku na prvním místě).
Problém 3:Nesprávné dočasné indexování tabulky
Stejně jako u běžných tabulek byste měli vytvářet pouze indexy, které budou skutečně použity pozdějším kódem dotazu, aby pomohly výkonu dotazu. Viděl jsem spoustu případů, kdy na dočasný sloupec tabulky existuje neshlukovaný index a indexy s jedním sloupcem, které jsou vybrány bez analýzy pozdějšího kódu, jsou často zcela zbytečné. Nyní zkombinujte zbytečné indexy bez klastrů s chybějícím filtrováním při naplňování dočasné tabulky a máte recept na enormní nafouknutí databáze tempdb.
Obecně je také rychlejší vytvořit indexy po naplnění tabulky. To poskytuje další bonus, že indexy budou mít přesné statistiky, což může dále pomoci dotazu, protože optimalizátor dotazu bude schopen provést přesný odhad mohutnosti.
Mít spoustu neshlukovaných indexů, které se nepoužívají, plýtvá nejen místem na disku, ale také časem potřebným k jejich vytvoření. Pokud je to v kódu, který se často spouští, odstranění těchto nepotřebných indexů, které se vytvářejí při každém spuštění kódu, může mít významný vliv na celkový výkon.
Problém 4:tempdb Latch Contention
Je docela běžné, že v tempdb existuje úzké hrdlo, které lze vysledovat zpět k dočasnému použití tabulky. Pokud existuje mnoho souběžných připojení, na kterých běží kód, který vytváří a ruší dočasné tabulky, přístup k alokačním bitmapám databáze v paměti se může stát významným úzkým hrdlem.
Důvodem je to, že pouze jedno vlákno může měnit alokační bitmapu a označit stránky (z dočasné tabulky) jako přidělené nebo uvolněné, takže všechna ostatní vlákna musí čekat, čímž se snižuje propustnost zátěže. Přestože od SQL Server 2005 existuje dočasná mezipaměť tabulek, není příliš velká a existují omezení týkající se toho, kdy lze dočasnou tabulku ukládat do mezipaměti (např. pouze když je menší než 8 MB).
Tradičními způsoby, jak tento problém obejít, bylo použití příznaku trasování 1118 a více datových souborů tempdb (další informace naleznete v tomto příspěvku na blogu), ale další věc, kterou je třeba zvážit, je úplné odstranění dočasných tabulek!
Shrnutí
Dočasné tabulky mohou být velmi užitečné, ale velmi snadno a běžně se používají nesprávně. Kdykoli píšete (nebo kontrolujete kód), který používá dočasnou tabulku, zvažte následující:
- Je tato dočasná tabulka opravdu potřebná? ?
- Je kód, který vyplňuje tabulku, při použití správného filtrování? omezit dočasnou velikost tabulky?
- Jsou indexy vytvářeny po naplnění tabulky (obecně) a jsou použité indexy pozdějším kódem?
Paul White má několik skvělých příspěvků (zde a zde) o dočasném použití objektů a ukládání do mezipaměti, které doporučuji také přečíst.
A ještě jedna poslední věc, pokud se rozhodnete nepoužít dočasnou tabulku, nenahraďte ji pouze proměnnou tabulky, běžným tabulkovým výrazem nebo kurzorem (to vše jsou běžné způsoby, jak se lidé snaží „optimalizovat“ dočasná tabulka) – vymyslete nejefektivnější způsob, jak (pře)psat kód – neexistuje žádná odpověď „jedna velikost pro všechny“.
Do příště přejeme hodně štěstí při odstraňování problémů!