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

SQL Server Temporary Object Caching

At lave en tabel er en relativt ressourcekrævende og tidskrævende operation. Serveren skal lokalisere og allokere lagerplads til de nye data- og indeksstrukturer og foretage de tilsvarende indtastninger i flere systemmetadatatabeller. Alt dette arbejde skal udføres på måder, der altid vil fungere korrekt under høj samtidighed, og som opfylder alle de ACID-garantier, der forventes af en relationel database.

I SQL Server betyder det, at man tager de rigtige slags låse og låse i den korrekte rækkefølge, samtidig med at man sikrer, at detaljerede transaktionslogposter er sikkert forpligtet til vedvarende lagring forud for fysiske ændringer i databasen. Disse logposter sikrer, at systemet kan bringe databasen tilbage til en konsistent tilstand i tilfælde af en tilbagerulning af transaktioner eller systemnedbrud.

At droppe et bord er en tilsvarende dyr operation. Heldigvis opretter eller dropper de fleste databaser ikke tabeller med nogen stor frekvens. Den åbenlyse undtagelse fra dette er systemdatabasen tempdb . Denne enkelte database indeholder det fysiske lager, allokeringsstrukturer, systemmetadata og transaktionslogposter for alle midlertidige tabeller og tabelvariabler på tværs af hele SQL Server-instansen.

Det er i karakter af midlertidige tabeller og tabelvariabler, der skal oprettes og slettes meget hyppigere end andre databaseobjekttyper. Når denne naturligt høje frekvens af oprettelse og ødelæggelse kombineres med den koncentrerende effekt af alle midlertidige tabeller og tabelvariabler, der er knyttet til en enkelt database, er det næppe overraskende, at der kan opstå uenighed i allokerings- og metadatastrukturerne i tempdb database.

Midlertidig objektcaching

For at reducere indvirkningen på tempdb strukturer, kan SQL Server cache midlertidige objekter til genbrug. I stedet for at slette et midlertidigt objekt beholder SQL Server systemets metadata og afkorter tabeldataene. Hvis tabellen er 8MB eller mindre, udføres trunkeringen synkront; ellers anvendes udskudt drop. I begge tilfælde reducerer trunkering lagerkravet til en enkelt (tom) dataside og allokeringsoplysningerne til en enkelt IAM-side.

Caching undgår næsten alle allokerings- og metadataomkostninger ved at oprette det midlertidige objekt næste gang. Som en bivirkning af at lave færre ændringer i tempdb database end en fuld drop- og genskabscyklus, reducerer midlertidig objektcache også mængden af ​​transaktionslogning påkrævet.

Opnåelse af cachelagring

Tabelvariabler og lokale midlertidige tabeller er begge i stand til at blive cachelagret. For at kvalificere sig til cachelagring skal en lokal midlertidig tabel eller tabelvariabel skal oprettes i et modul:

  • Lagret procedure (inklusive en midlertidig lagret procedure)
  • Udløser
  • Tabelvurderet funktion med flere sætninger
  • Skalær brugerdefineret funktion

Returværdien af ​​en multi-sætning tabel-værdi funktion er en tabel variabel, som i sig selv kan cachelagres. Parametre med tabelværdi (som også er tabelvariable) kan cachelagres, når parameteren sendes fra en klientapplikation, for eksempel i .NET-kode ved hjælp af SqlDbType.Structured . Når sætningen er parametriseret, kan tabelværdierede parameterstrukturer kun cachelagres på SQL Server 2012 eller nyere.

Følgende kan ikke cachelagres:

  • Globale midlertidige tabeller
  • Objekter oprettet ved hjælp af ad-hoc SQL
  • Objekter oprettet ved hjælp af dynamisk SQL (f.eks. ved hjælp af EXECUTE eller sys.sp_executesql )

For at blive cachelagret må et midlertidigt objekt desuden ikke :

  • Har navngivne begrænsninger (begrænsninger uden eksplicitte navne er helt i orden)
  • Udfør "DDL" efter objektoprettelse
  • Vær i et modul defineret ved hjælp af WITH RECOMPILE mulighed
  • Bliv kaldet ved hjælp af WITH RECOMPILE mulighed for EXECUTE erklæring

For at adressere nogle almindelige misforståelser eksplicit:

  • TRUNCATE TABLE ikke forhindre caching
  • DROP TABLE ikke forhindre caching
  • UPDATE STATISTICS ikke forhindre caching
  • Automatisk oprettelse af statistik ikke forhindre caching
  • Manuel CREATE STATISTICS vil forhindre caching

Alle midlertidige objekter i et modul vurderes for caching egnethed separat. Et modul, der indeholder et eller flere midlertidige objekter, der ikke kan cachelagres, kan stadig kvalificere sig til cachelagring af andre midlertidige objekter inden for samme modul.

Et almindeligt mønster, der deaktiverer caching for midlertidige tabeller, er oprettelsen af ​​indekser efter den indledende tabeloprettelsessætning. I de fleste tilfælde kan dette løses ved hjælp af primær nøgle og unikke begrænsninger. I SQL Server 2014 og nyere har vi mulighed for at tilføje ikke-unikke ikke-klyngede indekser direkte i tabeloprettelsessætningen ved hjælp af INDEX klausul.

Overvågning og vedligeholdelse

Vi kan se, hvor mange midlertidige objekter der i øjeblikket er cachelagret ved hjælp af cache-tællerne DMV:

VÆLG DOMCC.[type], DOMCC.pages_kb, DOMCC.pages_in_use_kb, DOMCC.entries_count, DOMCC.entries_in_use_countFROM sys.dm_os_memory_cache_counters AS DOMCC WHERE DOMCC.[name] =Nødvariables'Temporary;

Et eksempel på resultat er:

En cachepost anses for at være i brug så længe en del af det indeholdende modul kører. Samtidig udførelse af det samme modul vil resultere i, at der oprettes flere cachelagrede midlertidige objekter. Flere eksekveringsplaner for det samme modul (måske på grund af forskellig session SET optioner) vil også føre til flere cacheposter for det samme modul.

Cache-poster kan ældes over tid som svar på konkurrerende behov for hukommelse. Cachelagrede midlertidige objekter kan også fjernes (asynkront med en systemtråd i baggrunden), når det overordnede moduls eksekveringsplan fjernes fra plancachen.

Selvom det ikke understøttes (eller på nogen måde anbefales) for produktionssystemer, kan det midlertidige objektcachelager manuelt ryddes fuldstændigt til testformål med:

DBCC FREESYSTEMCACHE('Midlertidige tabeller og tabelvariabler') MED MARK_IN_USE_FOR_REMOVAL;WAITFOR DELAY '00:00:05';

De fem sekunders forsinkelse giver tid til, at baggrundsoprydningsopgaven kan køre. Bemærk, at denne kommando er faktisk farlig . Du bør kun bruge det (på egen risiko) på en testinstans, du har eksklusiv adgang til. Når du er færdig med at teste, genstart SQL Server-forekomsten.

Cachingimplementeringsdetaljer

Tabelvariabler implementeres af en 'rigtig' brugertabel i tempdb database (dog ikke en tabel, vi kan forespørge direkte på). Navnet på den tilknyttede tabel er "#" efterfulgt af den ottecifrede hexadecimale repræsentation af objekt-id'et. Følgende forespørgsel viser forholdet:

-- En tabelvariabelDECLARE @Z AS tabel (z heltal NULL); -- Tilsvarende sys.tables entrySELECT T.[navn], ObjIDFromName =CONVERT(heltal, CONVERT(binær(4), HØJRE(T.[navn], 8), 2)), T.[objekt_id], T.[ type_desc], T.create_date, T.modify_dateFROM tempdb.sys.tables AS T WHERE T.[navn] SOM N'#[0-9A-F][0-9A-F][0-9A-F][0 -9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]';

Et eksempelresultat er vist nedenfor. Bemærk, hvordan objekt-id'et beregnet ud fra objektnavnet matcher det faktiske objekt-id:

At køre det script som ad-hoc SQL vil producere en anden tempdb objekt-id (og objektnavn) på hver udførelse (ingen caching). Ved at placere det samme script inde i et modul (f.eks. en lagret procedure) vil tabelvariablen blive cachelagret (så længe dynamisk SQL ikke bruges), så objektets ID og navn vil være det samme ved hver udførelse.

Når tabelvariablen ikke er cachelagret, oprettes og slettes den underliggende tabel hver gang. Når midlertidig objektcache er aktiveret, afkortes tabellen i slutningen af ​​modulet i stedet for at blive slettet. Der er ingen ændringer til systemmetadata, når en tabelvariabel cachelagres. Indvirkningen på allokeringsstrukturer og transaktionslogning er begrænset til sletning af rækkerne i tabellen og fjernelse af overskydende data og allokeringssider, når modulet slutter.

Midlertidige tabeller

Når en midlertidig tabel bruges i stedet for en tabelvariabel, er den grundlæggende mekanisme stort set den samme, med blot et par ekstra omdøbningstrin:Når en midlertidig tabel ikke cachelagres , den er synlig i tempdb med det velkendte brugernavn, efterfulgt af en masse understregninger og den hexadecimale repræsentation af objekt-id'et som et endeligt suffiks. Den lokale midlertidige tabel forbliver, indtil den eksplicit slettes, eller indtil omfanget, som den blev oprettet i, slutter. For ad-hoc SQL betyder det, når sessionen afbrydes fra serveren.

Til en cachelagret midlertidig tabel , første gang modulet køres, oprettes den midlertidige tabel ligesom for den ikke-cachelagrede sag. I slutningen af ​​modulet, i stedet for at blive slettet automatisk (efterhånden som omfanget, hvor det blev oprettet, slutter), afkortes den midlertidige tabel og derefter omdøbes til den hexadecimale repræsentation af objekt-id'et (præcis som det ses for tabelvariablen). Næste gang modulet kører, omdøbes den cachelagrede tabel fra det hexadecimale format til det brugerangivne navn (plus understregninger plus hex-objekt-id).

De ekstra omdøbningsoperationer i starten og slutningen af ​​modulet involverer et lille antal systemmetadataændringer . Cachelagrede midlertidige tabeller kan derfor stadig opleve i det mindste nogle metadatastridigheder under meget høje genbrugsrater. Ikke desto mindre er metadatapåvirkningen af ​​en cachelagret midlertidig tabel meget lavere end for den ikke-cachelagrede sag (oprettelse og sletning af tabellen hver gang).

Flere detaljer og eksempler på, hvordan midlertidig objektcache fungerer, kan findes i min tidligere artikel.

Statistik om cachelagrede midlertidige tabeller

Som tidligere nævnt kan statistik være automatisk oprettet på midlertidige tabeller uden at miste fordelene ved midlertidig objektcache (som en påmindelse, vil manuelt oprettelse af statistik vil deaktiver caching).

En vigtig advarsel er, at statistikken knyttet til en cachelagret midlertidig tabel er ikke nulstillet når objektet er cachelagret i slutningen af ​​modulet, eller når det cachelagrede objekt hentes fra cachen i starten af ​​modulet. Som en konsekvens heraf kan statistik på en cachelagret midlertidig tabel blive tilbage fra en ikke-relateret tidligere udførelse. Med andre ord kan statistikken have absolut ingen sammenhæng til det aktuelle indhold af den midlertidige tabel.

Dette er naturligvis uønsket, da hovedårsagen til at foretrække en lokal midlertidig tabel frem for en tabelvariabel er tilgængeligheden af ​​nøjagtige distributionsstatistikker. Som afhjælpning vil statistikken automatisk blive opdateret, når (hvis) det akkumulerede antal ændringer af det underliggende cachelagrede objekt når den interne genkompileringstærskel. Dette er svært at vurdere på forhånd, fordi detaljerne er komplekse og noget kontraintuitive.

Den mest omfattende løsning, samtidig med at fordelene ved midlertidig objektcache bevares, er at:

  • Manuel UPDATE STATISTICS på det midlertidige bord i modulet; og
  • Tilføj en OPTION (RECOMPILE) hint til udsagn, der refererer til den midlertidige tabel

Naturligvis er der en omkostning forbundet med at gøre dette, men det er oftest acceptabelt. Faktisk, ved at vælge at bruge en lokal midlertidig tabel i første omgang, siger modulforfatteren implicit, at planvalg sandsynligvis vil være følsomt over for indholdet af den midlertidige tabel, så genkompilering kan give mening. Manuel opdatering af statistik sikrer, at de statistikker, der bruges under genkompileringen, afspejler det aktuelle indhold af tabellen (som vi helt sikkert ville forvente).

For flere detaljer om præcis, hvordan dette virker, se venligst min tidligere artikel om emnet.

Sammendrag og anbefalinger

Midlertidig objektcachelagring i et modul kan i høj grad reducere presset på delt allokering og metadatastrukturer i tempdb database. Den største reduktion vil forekomme, når du bruger tabelvariabler, fordi caching og genbrug af disse midlertidige objekter slet ikke involverer ændring af metadata (ingen omdøbningsoperationer). Uenighed om allokeringsstrukturer kan stadig ses, hvis den enkelte cachelagrede dataside er utilstrækkelig til at indeholde alle tabelvariablens data under kørsel.

Indvirkningen på plankvaliteten på grund af manglen på kardinalitetsoplysninger for tabelvariabler kan afbødes ved at bruge OPTION(RECOMPILE) eller sporingsflag 2453 (tilgængelig fra SQL Server 2012 og frem). Bemærk, at disse begrænsninger kun giver optimeringsoplysningerne om det samlede antal rækker i tabellen.

For at generalisere, tabel variabler bruges bedst, når dataene er små (ideelt set inden for en enkelt dataside for maksimale fordele), og når planvalget ikke afhænger af værdierne i tabelvariablen.

Hvis oplysninger om datadistributionen (densitet og histogrammer) er vigtigt for planvalg, brug en lokal midlertidig tabel i stedet. Sørg for at opfylde betingelserne for midlertidig tabelcaching, hvilket oftest betyder, at der ikke oprettes indekser eller statistikker efter den indledende tabeloprettelse. Dette er gjort mere bekvemt fra SQL Server 2014 og frem på grund af introduktionen af ​​INDEX klausul i CREATE TABLE udmelding.

En eksplicit UPDATE STATISTICS efter data er indlæst i den midlertidige tabel, og OPTION (RECOMPILE) tip til udsagn, der refererer til tabellen, kan være nødvendige for at producere alle de forventede fordele ved cachelagrede midlertidige tabeller i et modul.

Det er vigtigt kun at bruge midlertidige objekter, når de giver en klar fordel, oftest med hensyn til plankvalitet. Overdreven, ineffektiv eller unødvendig brug af midlertidige objekter kan føre til tempdb påstand, selv når der opnås midlertidig objektcache.

Optimal midlertidig objektcache er muligvis ikke nok til at reducere tempdb påstand til acceptable niveauer i alle tilfælde, selv hvor midlertidige genstande kun bruges, når det er fuldt berettiget. Brug af in-memory-tabelvariabler eller ikke-holdbare in-memory-tabeller kan give målrettede løsninger i sådanne tilfælde, selvom der altid er afvejninger, der skal foretages, og ingen enkelt løsning repræsenterer i øjeblikket den bedste løsning i alle tilfælde.


  1. Mysql-databasesynkronisering mellem to databaser

  2. Gør dine databasekomponenter meget tilgængelige (HA) via Load Balancers

  3. Konverter en række til flere rækker med færre kolonner

  4. Introduktion til PL/SQL-funktioner i Oracle-databasen