sql >> Database >  >> RDS >> Sqlserver

Caching van tijdelijke objecten van SQL Server

Het maken van een tabel is een relatief arbeidsintensieve en tijdrovende handeling. De server moet opslagruimte voor de nieuwe gegevens- en indexstructuren lokaliseren en toewijzen, en de overeenkomstige gegevens invoeren in meerdere systeemmetagegevenstabellen. Al dit werk moet worden gedaan op een manier die altijd correct werkt bij hoge gelijktijdigheid en die voldoet aan alle ACID-garanties die van een relationele database worden verwacht.

In SQL Server betekent dit dat de juiste soorten vergrendelingen en vergrendelingen in de juiste volgorde worden genomen, terwijl er ook voor wordt gezorgd dat gedetailleerde transactielogboekvermeldingen veilig worden vastgelegd in permanente opslag voorafgaand aan fysieke wijzigingen in de database. Deze logboekvermeldingen zorgen ervoor dat het systeem de database weer in een consistente staat kan brengen in het geval van een terugdraaiing van een transactie of een systeemcrash.

Een tafel laten vallen is een even dure operatie. Gelukkig maken of verwijderen de meeste databases niet met grote regelmaat tabellen. De voor de hand liggende uitzondering hierop is de systeemdatabase tempdb . Deze enkele database bevat de fysieke opslag, toewijzingsstructuren, systeemmetadata en transactielogboekvermeldingen voor alle tijdelijke tabellen en tabelvariabelen in de gehele SQL Server-instantie.

Het ligt in de aard van tijdelijke tabellen en tabelvariabelen om veel vaker te worden gemaakt en verwijderd dan andere typen databaseobjecten. Wanneer deze van nature hoge frequentie van creatie en vernietiging wordt gecombineerd met het concentrerende effect van alle tijdelijke tabellen en tabelvariabelen die zijn gekoppeld aan een enkele database, is het niet verwonderlijk dat er onenigheid kan ontstaan ​​in de allocatie- en metadatastructuren van de tempdb database.

Tijdelijke objectcaching

Om de impact op tempdb te verminderen structuren, kan SQL Server tijdelijke objecten cachen voor hergebruik. In plaats van een tijdelijk object te verwijderen, behoudt SQL Server de systeemmetagegevens en worden de tabelgegevens afgekapt. Als de tabel 8 MB of kleiner is, wordt de inkorting synchroon uitgevoerd; anders wordt uitgestelde daling gebruikt. In beide gevallen reduceert truncatie de opslagvereiste tot een enkele (lege) gegevenspagina en de toewijzingsinformatie tot een enkele IAM-pagina.

Caching vermijdt bijna alle toewijzings- en metadatakosten voor het maken van het tijdelijke object de volgende keer. Als neveneffect van het maken van minder wijzigingen aan de tempdb database dan een volledige cyclus van neerzetten en opnieuw maken, vermindert tijdelijke objectcaching ook de hoeveelheid transactieregistratie die vereist is.

Caching bereiken

Tabelvariabelen en lokale tijdelijke tabellen kunnen beide in de cache worden opgeslagen. Om in aanmerking te komen voor caching, moet een lokale tijdelijke tabel of tabelvariabele moet worden gemaakt in een module:

  • Opgeslagen procedure (inclusief een tijdelijk opgeslagen procedure)
  • Trigger
  • Functie met tabelwaarde met meerdere instructies
  • Scalaire door de gebruiker gedefinieerde functie

De retourwaarde van een functie met tabelwaarde met meerdere instructies is een tabelvariabele, die zelf in de cache kan worden opgeslagen. Tabelwaardeparameters (die ook tabelvariabelen zijn) kunnen in de cache worden opgeslagen wanneer de parameter wordt verzonden vanuit een clienttoepassing, bijvoorbeeld in .NET-code met behulp van SqlDbType.Structured . Wanneer de instructie is geparametriseerd, kunnen parameterstructuren met tabelwaarde alleen in de cache worden opgeslagen op SQL Server 2012 of hoger.

Het volgende kan niet in de cache worden opgeslagen:

  • Globale tijdelijke tabellen
  • Objecten gemaakt met ad-hoc SQL
  • Objecten gemaakt met dynamische SQL (bijv. met behulp van EXECUTE of sys.sp_executesql )

Om in de cache te worden opgeslagen, moet een tijdelijk object bovendien niet :

  • Restricties hebben genoemd (beperkingen zonder expliciete namen zijn prima)
  • Voer "DDL" uit na het maken van het object
  • Zorg dat u zich in een module bevindt die is gedefinieerd met de WITH RECOMPILE optie
  • Word gebeld met de WITH RECOMPILE optie van de EXECUTE verklaring

Om een ​​aantal veelvoorkomende misvattingen expliciet aan te pakken:

  • TRUNCATE TABLE niet caching voorkomen
  • DROP TABLE niet caching voorkomen
  • UPDATE STATISTICS niet caching voorkomen
  • Automatisch aanmaken van statistieken niet caching voorkomen
  • Handmatige CREATE STATISTICS zal caching voorkomen

Alle tijdelijke objecten in een module worden apart beoordeeld op cachinggeschiktheid. Een module die een of meer tijdelijke objecten bevat die niet in de cache kunnen worden opgeslagen, komt mogelijk nog steeds in aanmerking voor het cachen van andere tijdelijke objecten binnen dezelfde module.

Een veelvoorkomend patroon dat caching voor tijdelijke tabellen uitschakelt, is het maken van indexen na de initiële instructie voor het maken van tabellen. In de meeste gevallen kan dit worden omzeild met behulp van de primaire sleutel en unieke beperkingen. In SQL Server 2014 en later hebben we de mogelijkheid om niet-unieke niet-geclusterde indexen rechtstreeks toe te voegen aan de instructie voor het maken van tabellen met behulp van de INDEX clausule.

Bewaking en onderhoud

We kunnen zien hoeveel tijdelijke objecten momenteel in de cache zijn opgeslagen met behulp van de cache-tellers DMV:

SELECT 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] =Table N'Temporable 

Een voorbeeldresultaat is:

Een cache-item wordt beschouwd als in gebruik zolang een deel van de bevattende module wordt uitgevoerd. Gelijktijdige uitvoeringen van dezelfde module zullen ertoe leiden dat meerdere tijdelijke objecten in de cache worden gemaakt. Meerdere uitvoeringsplannen voor dezelfde module (misschien vanwege verschillende sessie SET opties) zal ook leiden tot meerdere cache-items voor dezelfde module.

Cache-items kunnen in de loop van de tijd verouderd raken als reactie op concurrerende geheugenbehoeften. Tijdelijke objecten in de cache kunnen ook worden verwijderd (asynchroon, door een achtergrondsysteemthread) wanneer het uitvoeringsplan van de bovenliggende module uit de plancache wordt verwijderd.

Hoewel niet ondersteund (of op geen enkele manier aanbevolen) voor productiesystemen, kan de tijdelijke objectcacheopslag handmatig volledig worden gewist voor testdoeleinden met:

DBCC FREESYSTEMCACHE('Tijdelijke tabellen en tabelvariabelen') WITH MARK_IN_USE_FOR_REMOVAL;WAITFOR DELAY '00:00:05';

De vertraging van vijf seconden zorgt ervoor dat de taak voor het opschonen van de achtergrond kan worden uitgevoerd. Merk op dat dit commando eigenlijk gevaarlijk is . Gebruik het alleen (op eigen risico) op een testexemplaar waartoe u exclusief toegang hebt. Als u klaar bent met testen, start u de SQL Server-instantie opnieuw.

Cache-implementatiedetails

Tabelvariabelen worden geïmplementeerd door een 'echte' gebruikerstabel in de tempdb database (hoewel het geen tabel is die we direct kunnen doorzoeken). De naam van de bijbehorende tabel is "#", gevolgd door de achtcijferige hexadecimale weergave van het object-ID. De volgende zoekopdracht toont de relatie:

-- Een tabelvariabeleDECLARE @Z AS tabel (z integer NULL); -- Overeenkomstige sys.tables entrySELECT T.[naam], ObjIDFromName =CONVERT(integer, CONVERT(binary(4), RIGHT(T.[name], 8), 2)), T.[object_id], T.[ type_desc], T.create_date, T.modify_dateFROM tempdb.sys.tables AS T WHERE T.[name] LIKE 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]';

Hieronder ziet u een voorbeeldresultaat. Merk op hoe de object-ID berekend op basis van de objectnaam overeenkomt met de werkelijke object-ID:

Als u dat script als ad-hoc SQL uitvoert, krijgt u een andere tempdb object-ID (en objectnaam) bij elke uitvoering (geen caching). Door hetzelfde script in een module te plaatsen (bijvoorbeeld een opgeslagen procedure) kan de tabelvariabele in de cache worden opgeslagen (zolang dynamische SQL niet wordt gebruikt), zodat de object-ID en naam bij elke uitvoering hetzelfde zijn.

Wanneer de tabelvariabele niet in de cache is opgeslagen, wordt de onderliggende tabel elke keer gemaakt en verwijderd. Wanneer tijdelijke objectcaching is ingeschakeld, wordt de tabel aan het einde van de module afgekapt in plaats van te worden verwijderd. Er zijn geen wijzigingen naar systeemmetadata wanneer een tabelvariabele in de cache wordt opgeslagen. De impact op allocatiestructuren en transactieregistratie is beperkt tot het verwijderen van de rijen in de tabel en het verwijderen van overtollige gegevens en allocatiepagina's wanneer de module eindigt.

Tijdelijke tabellen

Wanneer een tijdelijke tabel wordt gebruikt in plaats van een tabelvariabele, is het basismechanisme in wezen hetzelfde, met slechts een paar extra hernoemingsstappen:Wanneer een tijdelijke tabel niet in de cache is opgeslagen , het is zichtbaar in tempdb met de bekende door de gebruiker opgegeven naam, gevolgd door een aantal onderstrepingstekens en de hexadecimale weergave van het object-ID als laatste achtervoegsel. De lokale tijdelijke tabel blijft bestaan ​​totdat deze expliciet wordt verwijderd of totdat het bereik waarin deze is gemaakt, eindigt. Voor ad-hoc SQL betekent dit wanneer de verbinding met de server wordt verbroken.

Voor een tijdelijke tabel in cache , de eerste keer dat de module wordt uitgevoerd, wordt de tijdelijke tabel gemaakt, net als voor het geval zonder cache. Aan het einde van de module wordt de tijdelijke tabel niet automatisch verwijderd (omdat het bereik waarin deze is gemaakt eindigt) afgekapt en vervolgens hernoemd naar de hexadecimale weergave van het object-ID (precies zoals gezien voor de tabelvariabele). De volgende keer dat de module wordt uitgevoerd, wordt de tabel in de cache hernoemd van het hexadecimale formaat naar de door de gebruiker opgegeven naam (plus onderstrepingstekens plus hex-object-ID).

De extra hernoemingsoperaties aan het begin en einde van de module omvatten een klein aantal systeem metadatawijzigingen . Tijdelijke tabellen in de cache kunnen daarom nog steeds ten minste enige metadata-conflicten ondervinden bij zeer hoge hergebruikpercentages. Desalniettemin is de impact van metadata van een tijdelijke tabel in de cache veel lager dan voor de case zonder cache (de tabel elke keer maken en verwijderen).

Meer details en voorbeelden van hoe tijdelijke objectcaching werkt, vind je in mijn vorige artikel.

Statistieken over tijdelijke tabellen in de cache

Zoals eerder vermeld, kunnen statistieken automatisch gemaakt op tijdelijke tabellen zonder de voordelen van tijdelijke objectcaching te verliezen (ter herinnering:handmatig statistieken maken zal cache uitschakelen).

Een belangrijk voorbehoud is dat de statistieken gekoppeld aan een tijdelijke tabel in de cache worden niet gereset wanneer het object aan het einde van de module in de cache wordt opgeslagen, of wanneer het object in de cache wordt opgehaald uit de cache aan het begin van de module. Als gevolg hiervan kunnen er statistieken over een tijdelijke tabel in de cache overblijven van een niet-gerelateerde eerdere uitvoering. Met andere woorden, de statistieken kunnen absoluut geen relatie hebben naar de huidige inhoud van de tijdelijke tabel.

Dit is uiteraard onwenselijk, aangezien de belangrijkste reden om de voorkeur te geven aan een lokale tijdelijke tabel boven een tabelvariabele de beschikbaarheid van nauwkeurige distributiestatistieken is. Ter beperking worden de statistieken automatisch bijgewerkt wanneer (als) het geaccumuleerde aantal wijzigingen aan het onderliggende object in de cache de interne hercompilatiedrempel bereikt. Dit is vooraf moeilijk in te schatten, omdat de details complex en enigszins contra-intuïtief zijn.

De meest uitgebreide oplossing, met behoud van de voordelen van tijdelijke objectcaching, is om:

  • Handmatig UPDATE STATISTICS op de tijdelijke tafel binnen de module; en
  • Een OPTION (RECOMPILE) hint voor uitspraken die verwijzen naar de tijdelijke tabel

Natuurlijk zijn er kosten aan verbonden om dit te doen, maar dit is meestal acceptabel. Inderdaad, door ervoor te kiezen om in de eerste plaats een lokale tijdelijke tabel te gebruiken, zegt de auteur van de module impliciet dat planselectie waarschijnlijk gevoelig is voor de inhoud van de tijdelijke tabel, dus hercompilatie kan zinvol zijn. Het handmatig bijwerken van statistieken zorgt ervoor dat de statistieken die tijdens de hercompilatie worden gebruikt de huidige inhoud van de tabel weerspiegelen (zoals we zeker zouden verwachten).

Voor meer details over hoe dit precies werkt, zie mijn vorige artikel over dit onderwerp.

Samenvatting en aanbevelingen

Tijdelijke objectcaching binnen een module kan de druk op gedeelde toewijzings- en metadatastructuren in de tempdb aanzienlijk verminderen databank. De grootste reductie zal optreden bij het gebruik van tabelvariabelen, omdat het cachen en hergebruiken van deze tijdelijke objecten helemaal geen wijziging van metadata met zich meebrengt (geen hernoemingsbewerkingen). Er kan nog steeds een geschil bestaan ​​over toewijzingsstructuren als de enkele gegevenspagina in de cache onvoldoende is om alle gegevens van de tabelvariabele tijdens runtime te bevatten.

De impact op de kwaliteit van het plan als gevolg van het ontbreken van kardinaliteitsinformatie voor tabelvariabelen kan worden beperkt door OPTION(RECOMPILE) te gebruiken. of traceervlag 2453 (beschikbaar vanaf SQL Server 2012). Houd er rekening mee dat deze oplossingen de optimalisatie alleen informatie geven over het totale aantal rijen in de tabel.

Om te generaliseren, tabelvariabelen kunnen het beste worden gebruikt wanneer de gegevens klein zijn (idealiter passen binnen een enkele gegevenspagina voor maximale strijdvoordelen) en wanneer de keuze van het plan niet afhankelijk is van de waarden in de tabelvariabele.

Als informatie over de gegevensdistributie (dichtheid en histogrammen) is belangrijk voor planselectie, gebruik een lokale tijdelijke tabel in plaats van. Zorg ervoor dat u voldoet aan de voorwaarden voor tijdelijke tabelcaching, wat meestal betekent dat er geen indexen of statistieken worden gemaakt na de eerste instructie voor het maken van tabellen. Dit wordt vanaf SQL Server 2014 gemakkelijker gemaakt door de introductie van de INDEX clausule van de CREATE TABLE uitspraak.

Een expliciete UPDATE STATISTICS nadat de gegevens in de tijdelijke tabel zijn geladen, en OPTION (RECOMPILE) hints over instructies die verwijzen naar de tabel kunnen nodig zijn om alle verwachte voordelen van tijdelijke tabellen in de cache binnen een module te produceren.

Het is belangrijk om alleen tijdelijke objecten te gebruiken als ze een duidelijk voordeel opleveren, meestal in termen van plankwaliteit. Overmatig, inefficiënt of onnodig gebruik van tijdelijke objecten kan leiden tot tempdb conflict, zelfs wanneer tijdelijke objectcaching is bereikt.

Optimale tijdelijke objectcaching is mogelijk niet voldoende om tempdb te verminderen betwisting in alle gevallen tot een aanvaardbaar niveau, zelfs wanneer tijdelijke objecten alleen worden gebruikt wanneer dit volledig gerechtvaardigd is. Het gebruik van in-memory tabelvariabelen of niet-duurzame in-memory tabellen kan in dergelijke gevallen gerichte oplossingen bieden, hoewel er altijd afwegingen moeten worden gemaakt en geen enkele oplossing momenteel in alle gevallen de beste optie is.


  1. Hoe u deze 3 veelvoorkomende toegangsproblemen kunt oplossen

  2. Hoe een nummer naar een string in Oracle te converteren?

  3. ORA-12704:tekenset komt niet overeen

  4. MySQL:ongeldig gebruik van groepsfunctie