sql >> Database >  >> RDS >> Database

Compatibiliteitsniveaus en Cardinality Estimation Primer

Inleiding

Tussen 1998 en begin 2014 gebruikte SQL Server één kardinaliteitsschatter (CE), maar zou een nieuw databasecompatibiliteitsniveau introduceren voor elke nieuwe hoofdversie van SQL Server (met uitzondering van SQL Server 2008 R2). De native compatibiliteitsniveaus voor SQL Server worden weergegeven door de belangrijkste SQL Server-versie in Tabel 1:

SQL Server-versie Native Compatibiliteitsniveau
SQL Server 7.0 70
SQL Server 2000 80
SQL Server 2005 90
SQL Server 2008
SQL Server 2008 R2
100
SQL Server 2012 110
SQL Server 2014 120
SQL Server 2016 130
SQL Server 2017 140
SQL Server 2019 150

Tabel 1:SQL Server-versies en native compatibiliteitsniveaus

Tussen SQL Server 7.0 en SQL Server 2012 was er geen verband tussen het compatibiliteitsniveau van een database en de kardinaliteitsschatter die query's in die database zouden gebruiken. Dit komt omdat er maar één kardinaliteitsschatter was, die in 1998 een grote update kreeg. Het compatibiliteitsniveau van een database werd alleen gebruikt voor achterwaartse functionele compatibiliteit en om enkele nieuwe functies in elke nieuwe versie van SQL Server in of uit te schakelen (zie deze Stack Exchange-antwoord voor voorbeelden van hoe gedrag veranderde tussen 80 en 90, waarschijnlijk de meest ontwrichtende verandering). In tegenstelling tot de bestandsversie van een SQL Server-database, kunt u het compatibiliteitsniveau van een database op elk moment wijzigen in elk ondersteund compatibiliteitsniveau, met een eenvoudige ALTER DATABASE-opdracht.

Als u standaard een nieuwe database in SQL Server 2012, zou het compatibiliteitsniveau worden ingesteld op 110, maar u kunt dit desgewenst naar een eerder niveau wijzigen. Als je hersteld een databaseback-up van een SQL Server 2008-exemplaar naar een SQL Server 2012-exemplaar, zou het de bestandsversie van de database upgraden, maar het compatibiliteitsniveau laten zoals het was op het SQL Server 2008-exemplaar (tenzij het 80 was, wat zou upgrade naar 90, de minimale versie die wordt ondersteund door SQL Server 2012). Naast het fundamentele verschil tussen de bestandsversie van een database en het compatibiliteitsniveau van een database, hoefden de meeste DBA's en ontwikkelaars zich niet veel zorgen te maken over de compatibiliteitsniveaus van de database voordat SQL Server 2014 werd uitgebracht. In veel gevallen zijn de compatibiliteitsniveaus van de meeste databases nooit gewijzigd na een migratie naar een nieuwe versie van SQL Server. Dit veroorzaakte meestal geen problemen, tenzij u echt een nieuwe functie of nieuw gedrag nodig had dat is gewijzigd in het nieuwste databasecompatibiliteitsniveau.

SQL Server 2014-wijzigingen

Deze oude stand van zaken veranderde radicaal met de release van SQL Server 2014. SQL Server 2014 introduceerde een "nieuwe" kardinaliteitsschatter die standaard was ingeschakeld wanneer een database het compatibiliteitsniveau 120 had. In de klassieke whitepaper, "Uw queryplannen optimaliseren met de SQL Server 2014 Cardinality Estimator", legt Joe Sack de achtergrond en het gedrag van deze wijziging uit in april 2014. In veel gevallen verliepen de meeste van uw query's sneller bij gebruik van de nieuwe kardinaliteit schatter, maar met de nieuwe kardinaliteitsschatter kwam het vrij vaak voor dat er enkele query's werden uitgevoerd die grote prestatieregressies vertoonden. Als dat gebeurde, had SQL Server 2014 niet zoveel opties om de prestatieproblemen veroorzaakt door de nieuwe CE te verminderen. Joe's whitepaper behandelt die opties tot in detail, maar in wezen was je beperkt tot traceringsvlaggen op instantieniveau of query-hints op queryniveau om te bepalen welke kardinaliteitsschatter werd gebruikt door de query-optimizer, tenzij je wilde terugkeren naar compatibiliteitsniveau 110 of lager .

SQL Server 2016-wijzigingen

SQL Server 2016 heeft configuratieopties voor databasebereik geïntroduceerd, waarmee u bepaalde gedragingen kunt beheren die voorheen op instantieniveau waren geconfigureerd, met behulp van een ALTER DATABASE SCOPED CONFIGURATION-opdracht. In SQL Server 2016 omvatten deze opties MAXDOP, LEGACY_CARDINALITY ESTIMATION, PARAMETER_SNIFFING en QUERY_OPTIMIZER_HOTFIXES. Er was ook een CLEAR PROCEDURE_CACHE-optie waarmee je de hele plancache voor een enkele database kunt wissen.

Het meest relevant in deze context zijn de configuratie-opties LEGACY_CARDINALITY ESTIMATION en QUERY_OPTIMIZER_HOTFIXES met databasescope. LEGACY_CARDINALITY ESTIMATION schakelt de legacy CE in, ongeacht de instelling van het databasecompatibiliteitsniveau. Het is gelijk aan traceringsvlag 9481, maar het is alleen van invloed op de database in kwestie, niet op het hele exemplaar. Hiermee kunt u het compatibiliteitsniveau van de database instellen op 130 om een ​​aantal functionele en prestatievoordelen te krijgen, maar toch de oude CE-database voor de hele database te gebruiken (tenzij dit wordt overschreven door een query-hint op queryniveau).

De optie QUERY_OPTIMIZER_HOTFIXES is gelijk aan traceringsvlag 4199 op databaseniveau. SQL Server 2016 zal alle hotfixes voor query-optimalisatie inschakelen voor SQL Server 2016 RTM wanneer u het databasecompatibiliteitsniveau 130 gebruikt (zonder traceringsvlag 4199 in te schakelen). Als u TF 4199 of QUERY_OPTIMIZER_HOTFIXES inschakelt, krijgt u ook alle hotfixes voor query-optimalisatie die na zijn uitgebracht SQL Server 2016 RTM.

SQL Server 2016 SP1 heeft ook de USE HINT-queryhints geïntroduceerd die gemakkelijker te gebruiken, te begrijpen en te onthouden zijn dan de oudere QUERYTRACEON-queryhints. Dit geeft u een nog nauwkeuriger controle over het gedrag van optimalisatieprogramma's die verband houden met het compatibiliteitsniveau van de database en de versie van de kardinaliteitsschatter die wordt gebruikt. U kunt een query uitvoeren op sys.dm_exec_valid_use_hints om een ​​lijst met geldige USE HINT-namen te krijgen voor de exacte build van SQL Server die u gebruikt.

SQL Server 2017-wijzigingen

De nieuwe functie voor adaptieve queryverwerking is toegevoegd in SQL Server 2017 en is standaard ingeschakeld wanneer u databasecompatibiliteitsniveau 140 gebruikt.

Microsoft probeert af te stappen van de oude terminologie van "Nieuwe CE" en "Oude CE", aangezien er in elke nieuwe hoofdversie van SQL Server wijzigingen en oplossingen zijn voor de optimalisatie van query's. Hierdoor is er niet meer één “Nieuwe CE”. In plaats daarvan wil Microsoft verwijzen naar CE70 (standaard CE voor SQL Server 7.0 tot en met SQL Server 2012), CE120 voor SQL Server 2014, CE130 voor SQL Server 2016, CE140 voor SQL Server 2017 en CE150 voor SQL Server 2019. Beginnend met SQL Server 2017 CU10, kunt u de USE HINT-functionaliteit gebruiken om dit te regelen met queryhints. Bijvoorbeeld:

/*...query...*/ OPTION (USE HINT('QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_130'));

… zou een geldige vraaghint zijn om de CE130-kardinaliteitsschatter voor een bepaalde vraag te forceren.

SQL Server 2019-wijzigingen

SQL Server 2019 voegt nog meer prestatieverbeteringen en gedragsveranderingen toe die standaard zijn ingeschakeld wanneer een database compatibiliteitsmodus 150 gebruikt. Een goed voorbeeld is scalaire UDF-inlining. Een ander voorbeeld is de intelligente functie voor het verwerken van query's, die een superset is van de adaptieve queryverwerking in SQL Server 2017.

Er zijn vijf nieuwe USE HINT-opties, waaronder manieren om de batchmodus uit te schakelen of adaptieve geheugentoekenningsfeedback uit te schakelen, zoals weergegeven in Tabel 2:

DISABLE_BATCH_MODE_ADAPTIVE_JOINS
DISABLE_BATCH_MODE_MEMORY_GRANT_FEEDBACK
DISABLE_INTERLEAVED_EXECUTION_TVF
DISALLOW_BATCH_MODE
QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_150

Tabel 2:Nieuwe USE HINT-opties

En er zijn ook zestien nieuwe configuratieopties voor databasebereik (vanaf CTP 2.2) die u controle op databaseniveau geven over meer items die ook worden beïnvloed door traceringsvlaggen of databasecompatibiliteit. Het geeft u een meer fijnmazige controle over wijzigingen op een hoger niveau die standaard zijn ingeschakeld met databasecompatibiliteitsniveau 150. Deze staan ​​vermeld in Tabel 3:

ACCELERATED_PLAN_FORCING ELEVATE_RESUMABLE ROW_MODE_MEMORY_GRANT_FEEDBACK
BATCH_MODE_ADAPTIVE_JOINS GLOBAL_TEMPORARY_TABLE_AUTO_DROP TSQL_SCALAR_UDF_INLINING
BATCH_MODE_MEMORY_GRANT_FEEDBACK INTERLEAVED_EXECUTION_TVF XTP_PROCEDURE_EXECUTION_STATISTICS
BATCH_MODE_ON_ROWSTORE ISOLATE_SECURITY_POLICY_CARDINALITY XTP_QUERY_EXECUTION_STATISTICS
DEFERRED_COMPILATION_TV LIGHTWEIGHT_QUERY_PROFILING
ELEVATE_ONLINE OPTIMIZE_FOR_AD_HOC_WORKLOADS

Tabel 3:Nieuwe configuratie-opties voor databasebereik

Conclusie

Migreren naar een moderne versie van SQL Server (wat betekent SQL Server 2016 of nieuwer) is aanzienlijk ingewikkelder dan bij oudere versies van SQL Server. Vanwege de wijzigingen die zijn gekoppeld aan de verschillende databasecompatibiliteitsniveaus en verschillende versies van de kardinaliteitsschatter, is het eigenlijk heel belangrijk om na te denken, te plannen en daadwerkelijk te testen welk databasecompatibiliteitsniveau u wilt gebruiken op de nieuwe versie van SQL Server die u wilt gebruiken. migreren uw bestaande databases naar.

Het aanbevolen upgradeproces van Microsoft is om te upgraden naar de nieuwste SQL Server-versie, maar het compatibiliteitsniveau van de brondatabase te behouden. Schakel vervolgens Query Store in voor elke database en verzamel basislijngegevens over de werkbelasting. Vervolgens stelt u het compatibiliteitsniveau van de database in op de nieuwste versie en gebruikt u vervolgens Query Store om prestatieregressies op te lossen door het laatst bekende goede plan te forceren.

U wilt echt een lukrake "blinde" migratie vermijden, waarbij u niet weet hoe dit werkt en hoe uw werklast op deze veranderingen zal reageren. Het wijzigen van het compatibiliteitsniveau van de database naar een geschikte versie en het gebruik van de juiste configuratie-opties voor de database, samen met de juiste query-hints waar absoluut noodzakelijk, is uiterst belangrijk bij moderne versies van SQL Server.


  1. Een kolom wijzigen:null in niet null

  2. SQLite LIKE

  3. Willekeurige rijen selecteren in MySQL

  4. hoe meerdere strings samen te vervangen in Oracle