Během posledních 18 měsíců jsem se soustředil na trhavé reakce na analýzu statistik čekání a další témata související s laděním výkonu a v tomto příspěvku v tom budu pokračovat a diskutovat o PAGELATCH_XX čeká. XX na konci čekání znamená, že existuje několik typů PAGELATCH počkejte a nejběžnější příklady jsou:
- PAGELATCH_SH – ( SH are) čekají na přístup ke stránce datového souboru v paměti, aby bylo možné přečíst obsah stránky
- PAGELATCH_EX nebo PAGELATCH_UP – (EX včetně nebo NAHORU datum) čeká na přístup ke stránce datového souboru v paměti, aby bylo možné upravit obsah stránky
Když jeden z těchto typů čekání na serveru převládá, prudká reakce je taková, že problém souvisí s I/O (tj. záměna s PAGEIOLATCH_XX wait type, který jsem popsal v příspěvku z roku 2014) a někdo se pokusí přidat více paměti nebo vyladit I/O subsystém. Žádná z těchto reakcí nebude mít vůbec žádný účinek, protože sporné stránky datových souborů jsou již v paměti ve fondu vyrovnávací paměti!
Ve všech případech můžete zjistit, zda máte problém s PAGELATCH_XX spor pomocí sys.dm_os_waiting_tasks skript na mém blogu nebo pomocí nástroje jako Performance Advisor, jak je ukázáno (pro jiný typ čekání) v tomto příspěvku.
Co je tedy zdrojem sporu? Nejprve vysvětlím pozadí těchto typů čekání a poté proberu dvě nejčastější příčiny PAGELATCH_XX spor.
Pozadí:Západky
Než přejdu k některým příčinám PAGELATCH_XX Počkejte, chci vysvětlit, proč vůbec existují.
V každém vícevláknovém systému je třeba chránit datové struktury, ke kterým lze přistupovat a manipulovat s nimi více vláken, aby se zabránilo scénářům, jako jsou:
- Dvě vlákna aktualizují datovou strukturu současně a některé aktualizace jsou ztraceny
- Vlákno aktualizující datovou strukturu souběžně s jiným vláknem, které čte datovou strukturu, takže čtecí vlákno vidí směs starých a nových dat.
Toto je základní informatika a SQL Server se neliší, takže všechny datové struktury v SQL Serveru musí mít vícevláknové řízení přístupu.
Jeden z mechanismů, které k tomu SQL Server používá, se nazývá latch, kde držení latch ve výhradním režimu zabraňuje jiným vláknům v přístupu k datové struktuře a držení latch v režimu sdílení zabraňuje jiným vláknům ve změně datové struktury. SQL Server také používá spinlocky pro některé datové struktury a o nich jsem hovořil v tomto příspěvku v roce 2014.
Možná se ale divíte, proč je stránka datového souboru v paměti chráněna západkou? No, stránka datového souboru je pouze datová struktura, i když speciální, a proto potřebuje stejné řízení přístupu jako jakákoli jiná datová struktura. Když tedy jedno vlákno potřebuje upravit stránku datového souboru, potřebuje na stránce získat exkluzivní nebo aktualizovat latch, a pokud nemůže a musí počkat, typ čekání PAGELATCH_EX nebo PAGELATCH_UP výsledky.
Klasický spor tempdb
PAGELATCH spor v databázi tempdb je obvykle na alokačních bitmapách a vyskytuje se u úloh s mnoha souběžnými připojeními, které vytvářejí a ruší malé dočasné tabulky (které jsou uloženy v databázi tempdb).
Když je první řádek vložen do dočasné tabulky, musí být přiděleny dvě stránky (datová stránka a stránka IAM, která sleduje datovou stránku). Tyto stránky je třeba označit jako přidělené na speciální alokační stránce zvané PFS a ve výchozím nastavení jsou alokovány ze speciálních datových rozsahů, které jsou sledovány jinou alokační stránkou zvanou SGAM stránka (podrobnosti o nich lze nalézt v mém starém příspěvku na blogu tady). Když je dočasná tabulka zrušena, je třeba tyto stránky znovu uvolnit, což vyžaduje další změny na stránkách PFS a SGAM.
Pokud jsou dočasné tabulky malé a kumulativní velikost všech současně vytvořených dočasných tabulek je menší než 64 MB, pak jsou všechny tyto změny bitmapy přidělení soustředěny na úplně první stránky PFS a SGAM v datovém souboru tempdb (s ID stránky (1:1) respektive (1:3). Aktualizace jedné z těchto alokačních stránek vyžaduje zablokování stránky a stránku může měnit vždy pouze jedno vlákno, takže všechna ostatní vlákna musí čekat – s typem čekání PAGELATCH_UP .
Počínaje SQL Serverem 2005 lze dočasné tabulky při zrušení ukládat do mezipaměti, pokud jsou menší než 8 MB (a v SQL Server 2014 nejsou vytvořeny v uložené proceduře, která má v dočasné tabulce také příkazy DDL). To znamená, že další vlákno, které provádí stejný plán dotazů, může odebrat dočasnou tabulku z mezipaměti a nemusí se zabývat počátečními alokacemi. Tím se omezí spory o alokační bitmapy, ale mezipaměť dočasných tabulek není příliš velká, takže pracovní zatížení se stovkami souběžných vytvoření/zahození dočasných tabulek bude stále zaznamenávat spoustu sporů.
Je triviální zabránit sporům na stránkách SGAM v tempdb tím, že na serveru povolíte dokumentovaný příznak trasování 1118, o kterém říkám, že by měl být povolen na všech serverech po celém světě, a ve skutečnosti jde o neměnné výchozí chování v SQL Server 2016.
Zabránit sporům na stránkách PFS v tempdb je o něco obtížnější. Za předpokladu, že jsou dočasné tabulky potřebné pro výkon, je trik mít více datových souborů pro tempdb, takže alokace se provádějí mezi jednotlivými soubory, spor je rozdělen na více stránek PFS, takže celkový spor klesá. Bohužel neexistuje správná odpověď na to, kolik datových souborů byste měli mít. Více o obecně přijímaných pokynech v této věci si můžete přečíst v článku 2154845 znalostní báze KB a v tomto příspěvku na blogu.
Vložit hotspot
V uživatelských databázích je běžnou příčinou vysokého počtu PAGELATCH_EX waits je hotspot pro vložení.
K tomu může dojít, když má tabulka seskupený index s klíčem shluku int nebo bigint a velikost řádku je dostatečně malá, aby se na datovou stránku na úrovni listu seskupeného indexu vešlo mnoho desítek nebo více řádků tabulky.
Pokud u takové tabulky pracovní zátěž zahrnuje mnoho desítek nebo stovek souběžných vláken vkládání do tabulky, mnoho vláken vygeneruje řádky s hodnotami identity (a tedy klastrovými klíči), které je třeba vložit na stejnou datovou stránku na úrovni listu. .
Nyní si pamatujte, že provedení jakékoli změny na stránce datového souboru v paměti vyžaduje výhradní blokování, takže každé vlákno, které se pokouší vložit na stejnou stránku, musí získat výhradně blokování stránky. Zatímco každé vlákno drží výhradní západku, ostatní vlákna budou čekat na PAGELATCH_EX pro tuto stránku v podstatě dělá ze souběžných vložek velmi komplikovaný synchronní proces.
Existuje několik možných oprav tohoto problému:
- Použijte náhodnější klíč a uvědomte si, že to povede k fragmentaci indexu, takže použijte také faktor plnění indexu, který pomůže zabránit rozdělení stránky
- Rozložte vložky v tabulce pomocí nějakého umělého rozdělovacího mechanismu
- Použijte delší řádky tabulky (toto je samozřejmě nejméně přijatelná možnost)
Viděl jsem podobný hotspot vložení, když se někdo pokusil odstranit problémy s fragmentací indexu změnou náhodného klastrového klíče GUID na klíč klastru identity int nebo bigint, ale nepodařilo se mu otestovat nové schéma tabulky při produkčním zatížení.
Shrnutí
Stejně jako u jiných typů čekání přesně rozumíte PAGELATCH_XX čekání střední hodnota je klíčem k pochopení, jak je řešit.
Pokud jde o obecné statistiky čekání, více informací o jejich použití pro odstraňování problémů s výkonem naleznete v:
- Moje série příspěvků na blogu SQLskills, počínaje statistikou čekání, nebo mi prosím řekněte, kde to bolí
- Moje knihovna typů čekání a tříd Latch zde
- Online školicí kurz My Pluralsight SQL Server:Odstraňování problémů s výkonem pomocí statistiky čekání
- Poradce pro výkon SQL Sentry
Do příště přejeme hodně štěstí při odstraňování problémů!