sql >> Database teknologi >  >> RDS >> Database

Trimning af transaktionsloggen fedt

I mange SQL Server-arbejdsbelastninger, især OLTP, kan databasens transaktionslog være en flaskehals, der øger den tid, det tager en transaktion at gennemføre. De fleste mennesker antager, at I/O-undersystemet er den egentlige flaskehals, idet det ikke er i stand til at følge med mængden af ​​transaktionslog, der genereres af arbejdsbyrden.

Transaktionslogskriveforsinkelse

Latensen af ​​skriveoperationer til transaktionsloggen kan overvåges ved hjælp af sys.dm_io_virtual_file_stats DMV og korreleret med WRITELOG ventetider, der forekommer på systemet. Jeg optog en demovideo af analyse af transaktionslog I/O tilbage i 2011, så jeg vil ikke gentage alt det i dette indlæg. Du kan få videoen her og demokoden her (velegnet til at køre i produktion med det samme).

Hvis skriveforsinkelsen er højere end du ville forvente for dit I/O-undersystem, kan I/O-undersystemet ikke følge med, som den generelle antagelse er. Betyder det dog, at I/O-undersystemet skal forbedres? Ikke nødvendigvis.

På mange klientsystemer har jeg fundet ud af, at en betydelig del af logposter, der genereres, er unødvendige, og hvis du kan reducere antallet af logposter, der genereres, reducerer du mængden af ​​transaktionslog, der skrives til disken. Dette bør udmønte sig i en reduktion i skriveforsinkelse, hvilket reducerer transaktionsgennemførelsestiden.

Der er to hovedårsager til, at uvedkommende logposter genereres:ubrugte ikke-klyngede indekser og indekser, der bliver fragmenterede.

Ubrugte ikke-klyngede indekser

Når en post indsættes i en tabel, skal en post indsættes i hvert ikke-klyngede indeks, der er defineret i tabellen (med undtagelse af filtrerede indekser med passende filtre, som jeg vil ignorere fra dette tidspunkt). Dette betyder, at der genereres ekstra logposter, mindst én pr. ikke-klyngede indeks, for hver tabelindsættelse. Det samme gælder for sletning af en post i en tabel - de matchende poster skal slettes fra alle ikke-klyngede indekser. For en opdatering af en tabelpost opdateres ikke-klyngede indeksposter kun, hvis ikke-klyngede indeksnøglekolonne(r) eller inkluderede kolonne(r) var en del af opdateringen.

Disse operationer er naturligvis nødvendige for at holde hvert ikke-klyngede indeks korrekt i forhold til tabellen, men hvis det ikke-klyngede indeks er ubrugt af arbejdsbelastningen, er operationerne og logposterne produceret af dem unødvendige overhead. Ydermere, hvis disse ubrugte indekser bliver fragmenterede (hvilket jeg vil diskutere senere i dette indlæg), så vil de almindelige indeksvedligeholdelsesopgaver også fungere på dem, hvilket genererer endnu flere logposter (fra indekset REBUILD eller REORGANIZE operationer) helt unødvendigt.

Ubrugte indekser kommer fra en række forskellige kilder, såsom nogen, der ved en fejl har oprettet et indeks pr. tabelkolonne, nogen, der opretter hvert indeks foreslået af de manglende indeks-DMV'er, eller nogen, der opretter alle indekser foreslået af Database Tuning Advisor. Det kan også være, at arbejdsbyrdekarakteristikaene har ændret sig, og så det, der plejede at være nyttige indekser, ikke længere bliver brugt.

Uanset hvor de kom fra, bør ubrugte indekser fjernes for at reducere deres overhead. Du kan afgøre, hvilke indekser der er ubrugte ved at bruge sys.dm_db_index_usage_stats DMV, og jeg anbefaler, at du læser indlæg af mine kolleger Kimberly L. Tripp (her) og Joe Sack (her og her), da de forklarer, hvordan du bruger DMV korrekt.

Indeksfragmentering

De fleste mennesker tænker på indeksfragmentering som et problem, der påvirker forespørgsler, der skal læse store mængder data. Selvom dette er et af de problemer, som fragmentering kan forårsage, er fragmentering også et problem på grund af, hvordan det opstår.

Fragmentering er forårsaget af en operation kaldet en sideopdeling. Den enkleste årsag til en sideopdeling er, når en indekspost skal indsættes på en bestemt side (på grund af dens nøgleværdi), og siden ikke har nok ledig plads. I dette scenarie vil følgende handlinger finde sted:

  • En ny indeksside tildeles og formateres
  • Nogle af posterne fra hele siden flyttes til den nye side, hvorved der skabes ledig plads på den påkrævede side
  • Den nye side er linket til indeksstrukturen
  • Den nye post er indsat på den påkrævede side

Alle disse operationer genererer log-poster, og som du måske forestiller dig, kan dette være betydeligt mere, end der kræves for at indsætte en ny post på en side, der ikke kræver en sideopdeling. Tilbage i 2009 bloggede jeg en analyse af sideopdelingsomkostninger i form af transaktionsloggen og fandt nogle tilfælde, hvor en sideopdeling genererede over 40 gange mere transaktionslog end en almindelig indsættelse!

Det første skridt til at reducere de ekstra omkostninger er at fjerne ubrugte indekser, som jeg beskrev ovenfor, så de ikke genererer sideopdelinger. Det andet trin er at identificere resterende indekser, der er ved at blive fragmenterede (og derfor må lide under sideopdelinger) ved hjælp af sys.dm_db_index_physical_stats DMV (eller den nye SQL Sentry Fragmentation Manager) og proaktivt skabe ledig plads i dem ved hjælp af en indeksfyldningsfaktor. En fillfactor instruerer SQL Server til at efterlade tom plads på indekssider, når indekset bygges, genopbygges eller omorganiseres, så der er plads til at tillade nye poster at blive indsat uden at kræve en sideopdeling, og dermed skære ned på de ekstra genererede logposter.

Naturligvis er intet gratis - afvejningen, når du bruger fillfactors, er, at du proaktivt sørger for ekstra plads i indekserne for at forhindre, at flere logposter genereres - men det er normalt en god afvejning at lave. Det er relativt nemt at vælge en fillfactor, og det har jeg blogget om her.

Oversigt

At reducere skriveforsinkelsen for en transaktionslogfil betyder ikke altid, at man flytter til et hurtigere I/O-undersystem eller adskiller filen i sin egen del af I/O-undersystemet. Med nogle enkle analyser af indekserne i din database kan du muligvis reducere mængden af ​​transaktionslogposter, der genereres, betydeligt, hvilket fører til en tilsvarende reduktion i skriveforsinkelse.

Der er andre, mere subtile problemer, der kan påvirke transaktionsloggens ydeevne, og dem vil jeg undersøge i et fremtidigt indlæg.


  1. SQL-fejl:ORA-02000:mangler ALTID nøgleord, når der oprettes en identitetskolonnebaseret tabel

  2. Hvordan logger man PostgreSQL-forespørgsler?

  3. Pearsons korrelationskoefficientformel i SQL

  4. Sådan løses Problemet med godkendelsesplugin 'caching_sha2_password' kunne ikke indlæses