In dit artikel zullen we Database Scoped Configurations en SQL Server 2017 Automatic Plan Correction onderzoeken. Microsoft heeft nieuwe functies toegevoegd aan SQL Server 2017 die de queryprestaties hebben verbeterd.
De prestaties van SQL Server-query's zijn gerelateerd aan de kwaliteit en nauwkeurigheid van het uitvoeringsplan. Wanneer we een query uitvoeren, analyseert de query-optimizer veel uitvoeringsplannen en beslist vervolgens over het optimale uitvoeringsplan voor query's.
Verouderde kardinaliteitsschatting: De Cardinality Estimator voorspelt hoeveel rijen de query zal retourneren en bepaalt ook de geheugentoewijzing van de query.
In SQL Server 2017 is de standaardversie van het kardinaliteitsschattingsmodel 14.0, maar als u de oudere versie 7.0 van de kardinaliteitschatter wilt gebruiken, kunt u dit doen door de optie Legacy Cardinality Estimation te wijzigen in de Database Scoped Configurations sectie.
De standaardwaarde van de oude kardinaliteitsschatting is UIT. Dus als u de oudere versie wilt gebruiken, moet u deze op AAN zetten.
U kunt deze eigenschap ook wijzigen in T-SQL.
ALTER DATABASE SCOPED CONFIGURATION SET LEGACY_CARDINALITY_ESTIMATION = OFF|ON;
Als u deze instelling echter inschakelt, heeft dit invloed op alle query's. Als gevolg hiervan kan dit de prestaties van de query schaden. Om dit te voorkomen, kun je de FORCE_LEGACY_CARDINALITY_ESTIMATION hint gebruiken.
Wanneer we deze query uitvoeren in de WideWorldImporters-database, wordt automatisch een nieuwe versie van de kardinaliteitsschatting gebruikt.
SELECT [o].[CustomerID], o.LastEditedBy , [o].[OrderDate] FROM Sales.Orders o WHERE [o].[OrderDate] >= '20140101'
Wanneer we FORCE_LEGACY_CARDINALITY_ESTIMATION aan de query toevoegen, gebruikt de query-optimizer de vorige of oudste versie van de schatting van de kardinaliteit.
MAXDOP : we kunnen de maximale mate van parallellisme instellen voor een individuele database. Voordat deze functie was gemaakt, konden we alleen het MAXDOP-serverniveau configureren.
Met de MAXDOP-queryhint kunnen we query's parallel uitvoeren.
ALTER DATABASE SCOPED CONFIGURATION SET MAXDOP = 4; GO
Parametersnuiven: Wanneer de uitvoeringstijd van een query drastisch verandert en deze tijdswijziging is gerelateerd aan de queryparameter, wordt dit parameter sniffing genoemd.
Nu gaan we een opgeslagen procedure maken in de AdventureWorks-database. We sturen verschillende parameters en vergelijken uitvoeringsplannen.
DROP PROCEDURE IF EXISTS Get_Orders GO CREATE PROCEDURE Get_Orderes @ProductID INT AS SELECT SalesOrderDetailID, OrderQty FROM Sales.SalesOrderDetail WHERE ProductID = @ProductID; GO /******* Don t use this script in production servers! *******/ DBCC FREEPROCCACHE --Query Mars EXEC Get_OrderID_OrderQty @ProductID=870 DBCC FREEPROCCACHE --Query Venus EXEC Get_OrderID_OrderQty @ProductID=897
Zoals in de onderstaande afbeelding wordt weergegeven, genereert SQL Server een ander uitvoeringsplan voor dezelfde query. Het uitvoeringsplan van Query Mars beveelt een index aan. De queryparameter verandert het optimale uitvoeringsplan.
Voer deze query uit en bekijk de uitvoeringsplannen.
DBCC FREEPROCCACHE --Query Mars EXEC Get_OrderID_OrderQty @ProductID=870 --Query Venus EXEC Get_OrderID_OrderQty @ProductID=897
Het uitvoeringsplan voor Query Venus is hetzelfde als het uitvoeringsplan voor Query Mars. Dit is de parameter sniffing omdat het uitvoeringsplan in de cache is samengesteld voor het uitvoeringsplan van Query Mars. Daarom gebruikt Query Venus hetzelfde uitvoeringsplan.
Nu zullen we het snuiven van parameters uitschakelen en dezelfde zoekopdrachten uitvoeren.
ALTER DATABASE SCOPED CONFIGURATION SET PARAMETER_SNIFFING =OFF; DBCC FREEPROCCACHE --Query Mars EXEC Get_OrderID_OrderQty @ProductID=870 --Query Venus EXEC Get_OrderID_OrderQty @ProductID=897
Laten we eens kijken:
De SQL Server Query-optimizer genereerde het optimale uitvoeringsplan voor Query Venus en Query Mars. Deze benadering zorgt voor de optimale prestatie van de query.
Er zijn enkele opties om dit probleem te vermijden:
- OPTIE(OPNIEUW COMPILEREN)
- OPTIE (OPTIMALISEREN VOOR(@VARIABLE=UNKNOWN))
Automatische plancorrectie
SQL Server 2017 bevat een nieuwe functie genaamd Automatic Plan Correction. Wanneer we een query uitvoeren, maakt de query-optimizer een uitvoeringsplan. Om bepaalde redenen kiest de query-optimizer verkeerde uitvoeringsplannen. Enkele van de redenen zijn als volgt:
- Een zoekopdracht die niet aan de prestatiecriteria voldoet
- Verouderde statistieken
- Ongeschikte indexen
Wanneer de query-optimizer van SQL Server besluit het uitvoeringsplan te wijzigen en dit uitvoeringsplan de prestaties schaadt, wordt de queryprestatie de planregressie genoemd. Een nieuwe functie wordt geleverd met SQL Server 2016. Deze tool helpt bij het bewaken en oplossen van problemen met de prestaties van query's en slaat tegelijkertijd prestatiestatistieken en tellers van de uitvoering van de query op.
We kunnen deze opties inschakelen onder database-eigenschappen.
Nu gaan we een demo maken van deze functie. Maak eerst de procedurecache leeg en maak een opgeslagen procedure.
/**************************************** Don t use this script in production servers *****************************************/ USE WideWorldImporters ALTER DATABASE WideWorldImporters SET QUERY_STORE = ON; ALTER DATABASE [WideWorldImporters] SET QUERY_STORE CLEAR ALL DBCC FREEPROCCACHE --This command will clear all procedure cache in SQL Server. Dont try in production envoierment-- ALTER DATABASE WideWorldImporters SET AUTOMATIC_TUNING (FORCE_LAST_GOOD_PLAN = OFF); DROP PROCEDURE IF EXISTS Test_CoddingSight2 GO CREATE PROC Test_CoddingSight2 @Id AS INT AS select sum([UnitPrice]*[Quantity]) from Sales.OrderLines O INNER JOIN sales.Orders o1 ON o1.OrderID = o.OrderID where o.PackageTypeID = @Id
Bij deze stap zullen we deze procedure met verschillende parameters uitvoeren en het verschil in uitvoeringstijd vinden.
--Query Alpha DBCC FREEPROCCACHE EXEC Test_CoddingSight2 7 GO 80 DBCC FREEPROCCACHE EXEC Test_CoddingSight2 -1 --Query Beta EXEC Test_CoddingSight2 7 GO 80
Zoals u kunt zien, werd de eerste zoekopdracht in 12 seconden voltooid, terwijl de tweede in 33 seconden werd voltooid. De reden voor dit dramatische verschil is dat de query-optimizer een ongeschikt uitvoeringsplan voor Query Beta kiest.
Laten we de uitvoeringsplannen van Query Alpha en Query Beta vergelijken.
Uitvoeringsplan van Query Alpha
Uitvoeringsplan van Query Beta
In de bovenstaande afbeeldingen maakt de query-optimizer verschillende uitvoeringsplannen voor dezelfde query. Als we kijken naar Topbronnen die zoekopdrachten verbruiken , kunnen we zien dat Query Beta meer bronnen verbruikt dan Query Alpha.
De onderstaande zoekopdracht levert gedetailleerde informatie op over de afstemmingsaanbevelingen.
SELECT name, reason, score, JSON_VALUE(details, '$.implementationDetails.script') as script, details.* FROM sys.dm_db_tuning_recommendations CROSS APPLY OPENJSON(details, '$.planForceDetails') WITH ( query_id int '$.queryId', regressed_plan_id int '$.regressedPlanId', last_good_plan_id int '$.recommendedPlanId') as details WHERE JSON_VALUE(state, '$.currentValue') = 'Active'
De redenkolom laat zien waarom we deze aanbeveling moeten toepassen.
Nu zullen we Query Alpha en Query Beta opnieuw uitvoeren met de automatische plancorrectie ingeschakeld.
/**************************************** Don't use this script in production servers *****************************************/ ALTER DATABASE [WideWorldImporters] SET QUERY_STORE CLEAR ALL DBCC FREEPROCCACHE /**************************************** Enable Automatic Plan Correction *****************************************/ ALTER DATABASE WideWorldImporters SET AUTOMATIC_TUNING (FORCE_LAST_GOOD_PLAN = ON); --Query Alpha DBCC FREEPROCCACHE EXEC Test_CoddingSight2 7 GO 80 DBCC FREEPROCCACHE EXEC Test_CoddingSight2 -1 --Query Beta EXEC Test_CoddingSight2 7 GO 80
Na deze demo wordt het uitvoeringsplan Query Alpha toegepast op de Query Beta. Bovendien liggen de uitvoeringstijden van Query Alpha en Query Beta dicht bij elkaar. De onderstaande vraag retourneert de automatische plancorrectiestatus.
SELECT name, reason, score,JSON_VALUE(state, '$.currentValue') as status, JSON_VALUE(details, '$.implementationDetails.script') as script, details.* FROM sys.dm_db_tuning_recommendations CROSS APPLY OPENJSON(details, '$.planForceDetails') WITH ( query_id int '$.queryId', regressed_plan_id int '$.regressedPlanId', last_good_plan_id int '$.recommendedPlanId') as details WHERE JSON_VALUE(state, '$.currentValue') = 'Verifying'
We kunnen ook wat grafische informatie vinden in Queries with Forced Plans . Deze grafiek definieert de geforceerde zoekopdrachten en zoekopdrachten.
Referenties
Automatische plancorrectie in SQL Server 2017
Kardinaliteitsschatting