sql >> Databáze >  >> RDS >> Database

Oříznutí tuku protokolu transakcí

V mnoha úlohách SQL Server, zejména OLTP, může být protokol transakcí databáze překážkou, která zkracuje dobu potřebnou k dokončení transakce. Většina lidí předpokládá, že I/O subsystém je skutečným úzkým hrdlem, protože není schopen držet krok s množstvím transakčního protokolu generovaného pracovní zátěží.

Latence zápisu do protokolu transakcí

Latenci operací zápisu do protokolu transakcí lze sledovat pomocí sys.dm_io_virtual_file_stats DMV a koreluje s WRITELOG čekání, která se v systému vyskytují. V roce 2011 jsem nahrál demo video analýzy I/O protokolu transakcí, takže to v tomto příspěvku nebudu opakovat. Video můžete získat zde a demo kód zde (vhodné pro okamžité spuštění ve výrobě).

Pokud je latence zápisu vyšší, než byste očekávali pro váš I/O subsystém, pak I/O subsystém nemůže držet krok, jak je obecný předpoklad. Znamená to, že je třeba zlepšit I/O subsystém? Ne nutně.

Na mnoha klientských systémech jsem zjistil, že značná část generovaných záznamů protokolu je zbytečná, a pokud můžete snížit počet generovaných záznamů protokolu, snížíte množství protokolu transakcí zapsaných na disk. To by se mělo promítnout do snížení latence zápisu, čímž se zkrátí doba dokončení transakce.

Existují dvě hlavní příčiny generování nadbytečných záznamů protokolu:nepoužívané indexy bez klastrů a fragmentace indexů.

Nepoužité indexy bez klastrů

Kdykoli je záznam vložen do tabulky, musí být záznam vložen do každého neshlukovaného indexu definovaného v tabulce (s výjimkou filtrovaných indexů s příslušnými filtry, které budu od tohoto bodu ignorovat). To znamená, že pro každou vložku tabulky jsou generovány další záznamy protokolu, alespoň jeden na neshlukovaný index. Totéž platí pro mazání záznamu v tabulce – odpovídající záznamy musí být odstraněny ze všech neshlukovaných indexů. Pro aktualizaci záznamu tabulky se neklastrované indexové záznamy aktualizují pouze tehdy, pokud byly součástí aktualizace neklastrované sloupce indexového klíče nebo zahrnuté sloupce.

Tyto operace jsou samozřejmě nutné k tomu, aby každý neshlukovaný index byl s ohledem na tabulku správný, ale pokud není neshlukovaný index pracovní zátěží využíván, pak operace a jimi vytvořené záznamy protokolu jsou zbytečnou režií. Kromě toho, pokud se tyto nepoužívané indexy roztříští (o čemž budu diskutovat později v tomto příspěvku), pak na nich budou fungovat i běžné úlohy údržby indexu, které budou generovat ještě více záznamů protokolu (z indexu REBUILD nebo REORGANIZE operace) zcela zbytečně.

Nepoužité indexy pocházejí z různých zdrojů, například někdo omylem vytvořil index pro každý sloupec tabulky, někdo vytvořil každý index navržený chybějícími indexovými DMV nebo někdo vytvořil všechny indexy navržené Poradcem pro ladění databáze. Může se také stát, že se charakteristiky zátěže změnily, a tak se již nepoužívají to, co bývaly užitečné indexy.

Ať pocházejí odkudkoli, nepoužívané indexy by měly být odstraněny, aby se snížila jejich režie. Pomocí DMV sys.dm_db_index_usage_stats můžete určit, které indexy se nepoužívají, a doporučuji vám přečíst si příspěvky mých kolegů Kimberly L. Tripp (zde) a Joe Sacka (zde a zde), protože vysvětlují, jak správně používat DMV.

Fragmentace indexu

Většina lidí považuje fragmentaci indexu za problém, který ovlivňuje dotazy, které musí číst velké množství dat. I když je to jeden z problémů, které fragmentace může způsobit, fragmentace je také problémem kvůli tomu, jak k ní dochází.

Fragmentace je způsobena operací zvanou rozdělení stránky. Nejjednodušší příčinou rozdělení stránky je, když musí být na konkrétní stránku vložen záznam indexu (kvůli hodnotě klíče) a stránka nemá dostatek volného místa. V tomto scénáři proběhnou následující operace:

  • Je přidělena a naformátována nová stránka indexu
  • Některé záznamy z celé stránky se přesunou na novou stránku, čímž se vytvoří volné místo na požadované stránce
  • Nová stránka je propojena se strukturou indexu
  • Nový záznam se vloží na požadovanou stránku

Všechny tyto operace generují záznamy protokolu, a jak si dokážete představit, může to být podstatně více, než je potřeba k vložení nového záznamu na stránku, která nevyžaduje rozdělení stránky. V roce 2009 jsem napsal na blog analýzu nákladů na rozdělení stránky z hlediska protokolu transakcí a našel jsem několik případů, kdy rozdělení stránky vygenerovalo více než 40krát více protokolu transakcí než běžné vložení!

Prvním krokem ke snížení dodatečných nákladů je odstranění nepoužívaných indexů, jak jsem popsal výše, aby negenerovaly rozdělení stránek. Druhým krokem je identifikace zbývajících indexů, které se stávají fragmentovanými (a proto musí trpět rozdělením stránek) pomocí sys.dm_db_index_physical_stats DMV (neboli nový SQL Sentry Fragmentation Manager) a proaktivně v nich vytvářet volné místo pomocí indexu fillfactor. Fillfactor instruuje SQL Server, aby ponechal prázdné místo na stránkách indexu, když je index sestaven, přestavěn nebo reorganizován, takže je zde prostor pro vložení nových záznamů bez nutnosti rozdělení stránky, čímž se omezí další generované záznamy protokolu.

Samozřejmě nic není zadarmo – kompromisem při používání fillfactors je, že proaktivně poskytujete další prostor v indexech, abyste zabránili generování dalších záznamů protokolu – ale to je obvykle dobrý kompromis. Výběr fillfactoru je relativně snadný a napsal jsem o tom blog zde.

Shrnutí

Snížení latence zápisu souboru protokolu transakcí neznamená vždy přechod na rychlejší I/O subsystém nebo oddělení souboru do jeho vlastní části I/O subsystému. S jednoduchou analýzou indexů ve vaší databázi můžete být schopni výrazně snížit množství generovaných záznamů transakčního protokolu, což povede k úměrnému snížení latence zápisu.

Existují další, jemnější problémy, které mohou ovlivnit výkon protokolu transakcí, a ty prozkoumám v budoucím příspěvku.


  1. 3 způsoby, jak vrátit počet řádků v každém oddílu na serveru SQL (T-SQL)

  2. Jak používat STRCMP() k porovnání 2 řetězců v MySQL

  3. Předání názvu tabulky jako parametru v psycopg2

  4. jak přidat sekundu do časového razítka oracle