Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Konfigurationen im Bereich der SQL Server-Datenbank und automatische Plankorrektur

In diesem Artikel untersuchen wir Konfigurationen im Datenbankbereich und die automatische Plankorrektur von SQL Server 2017. Microsoft hat SQL Server 2017 neue Funktionen hinzugefügt, die die Abfrageleistung verbessert haben.

Die Abfrageleistung von SQL Server hängt von der Qualität und Genauigkeit des Ausführungsplans ab. Wenn wir eine Abfrage ausführen, analysiert der Abfrageoptimierer viele Ausführungspläne und entscheidet dann über den optimalen Abfrageausführungsplan.

Legacy-Kardinalitätsschätzung: Der Kardinalitätsschätzer sagt voraus, wie viele Zeilen die Abfrage zurückgeben wird, und bestimmt die Speicherzuweisung der Abfrage.

In SQL Server 2017 ist die Standardversion des Kardinalitätsschätzungsmodells 14.0, aber wenn Sie die ältere Version 7.0 des Kardinalitätsschätzers verwenden möchten, können Sie dies tun, indem Sie die Option Legacy Cardinality Estimation in Database Scoped Configurations ändern. stark> Abschnitt.

Der Standardwert der Legacy-Kardinalitätsschätzung ist AUS. Wenn Sie also die ältere Version verwenden möchten, müssen Sie diese auf ON stellen.

Alternativ können Sie diese Eigenschaft in T-SQL ändern.

ALTER DATABASE
    SCOPED CONFIGURATION  
        SET LEGACY_CARDINALITY_ESTIMATION = OFF|ON;

Wenn Sie diese Einstellung jedoch aktivieren, wirkt sich dies auf alle Abfragen aus. Dadurch kann die Abfrageleistung beeinträchtigt werden. Um dies zu verhindern, können Sie den Hinweis FORCE_LEGACY_CARDINALITY_ESTIMATION verwenden.

Wenn wir diese Abfrage in der WideWorldImporters-Datenbank ausführen, wird automatisch eine neue Version der Kardinalitätsschätzung verwendet.

SELECT
    [o].[CustomerID],
    o.LastEditedBy ,
    [o].[OrderDate]
    

FROM Sales.Orders o

WHERE [o].[OrderDate] >= '20140101'

Wenn wir der Abfrage FORCE_LEGACY_CARDINALITY_ESTIMATION hinzufügen, verwendet der Abfrageoptimierer die vorherige oder älteste Version der Kardinalitätsschätzung.

MAXDOP : wir können den maximalen Parallelitätsgrad für eine einzelne Datenbank festlegen. Bevor diese Funktion erstellt wurde, konnten wir nur die MAXDOP-Serverebene konfigurieren.

Der MAXDOP-Abfragehinweis ermöglicht es uns, Abfragen parallel auszuführen.

ALTER DATABASE  SCOPED CONFIGURATION 
 SET MAXDOP = 4;
 GO

Parameter-Sniffing: Wenn sich die Ausführungszeit einer Abfrage dramatisch ändert und diese Zeitänderung mit dem Abfrageparameter zusammenhängt, wird dies als Parameter-Sniffing bezeichnet.

Jetzt erstellen wir eine gespeicherte Prozedur in der AdventureWorks-Datenbank. Wir werden verschiedene Parameter senden und Ausführungspläne vergleichen.

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

Wie in der folgenden Abbildung gezeigt, generiert SQL Server einen anderen Ausführungsplan für dieselbe Abfrage. Der Ausführungsplan von Query Mars empfiehlt einen Index. Der Abfrageparameter ändert den optimalen Ausführungsplan.

Führen Sie diese Abfrage aus und sehen Sie sich die Ausführungspläne an.

DBCC FREEPROCCACHE
--Query Mars
EXEC Get_OrderID_OrderQty @ProductID=870

--Query Venus
EXEC Get_OrderID_OrderQty @ProductID=897

Der Ausführungsplan von Query Venus ist mit dem Ausführungsplan von Query Mars identisch. Dies ist das Parameter-Sniffing, da der zwischengespeicherte Ausführungsplan für den Query Mars-Ausführungsplan kompiliert wird. Aus diesem Grund verwendet Query Venus denselben Ausführungsplan.

Jetzt werden wir das Parameter-Sniffing deaktivieren und dieselben Abfragen ausführen.

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

Untersuchen wir:

Der SQL Server-Abfrageoptimierer generierte den optimalen Ausführungsplan für Query Venus und Query Mars. Dieser Ansatz bietet die optimale Leistung für die Abfrage.

Es gibt einige Optionen, um dieses Problem zu vermeiden:

  • OPTION(NEU KOMPILIEREN)
  • OPTION (OPTIMIEREN FÜR(@VARIABLE=UNBEKANNT))

Automatische Plankorrektur

SQL Server 2017 enthält ein neues Feature namens Automatische Plankorrektur. Wenn wir eine Abfrage ausführen, erstellt der Abfrageoptimierer einen Ausführungsplan. Aus bestimmten Gründen wählt der Abfrageoptimierer falsche Ausführungspläne aus. Einige der Gründe sind wie folgt:

  • Eine Abfrage, die Leistungskriterien nicht erfüllt
  • Veraltete Statistiken
  • Ungeeignete Indizes

Wenn der SQL Server-Abfrageoptimierer beschließt, den Ausführungsplan zu ändern, und dieser Ausführungsplan die Leistung beeinträchtigt, wird die Abfrageleistung als Planregression bezeichnet. Eine neue Funktion kommt mit SQL Server 2016. Dieses Tool hilft bei der Überwachung und Fehlerbehebung der Abfrageleistung und speichert gleichzeitig Leistungsmetriken und Zähler der Abfrageausführung.

Wir können diese Optionen unter Datenbankeigenschaften aktivieren.

Jetzt werden wir eine Demo dieser Funktion erstellen. Löschen Sie zunächst den Prozedurcache und erstellen Sie eine gespeicherte Prozedur.

/****************************************
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

In diesem Schritt führen wir dieses Verfahren mit unterschiedlichen Parametern aus und ermitteln den Unterschied in der Ausführungszeit.

--Query Alpha
DBCC FREEPROCCACHE 
EXEC Test_CoddingSight2 7
GO 80

DBCC FREEPROCCACHE 
EXEC Test_CoddingSight2 -1
--Query Beta
EXEC Test_CoddingSight2 7
GO 80

Wie Sie sehen können, wurde die erste Abfrage in 12 Sekunden abgeschlossen, während die zweite in 33 Sekunden abgeschlossen war. Der Grund für diesen dramatischen Unterschied liegt darin, dass der Abfrageoptimierer einen ungeeigneten Ausführungsplan für Query Beta auswählt.

Vergleichen wir die Ausführungspläne von Query Alpha und Query Beta.

Ausführungsplan von Query Alpha

Ausführungsplan von Query Beta

In den obigen Abbildungen erstellt der Abfrageoptimierer verschiedene Ausführungspläne für dieselbe Abfrage. Wenn wir uns Suchanfragen mit dem höchsten Ressourcenverbrauch ansehen , können wir sehen, dass Query Beta mehr Ressourcen verbraucht als Query Alpha.

Die folgende Abfrage gibt detaillierte Informationen zu den Tuning-Empfehlungen zurück.

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'

Die Spalte „Grund“ zeigt, warum wir diese Empfehlung anwenden müssen.

Jetzt werden wir Query Alpha und Query Beta mit aktivierter automatischer Plankorrektur erneut ausführen.

/****************************************
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

Nach dieser Demo wird der Query Alpha-Ausführungsplan auf Query Beta angewendet. Außerdem liegen die Ausführungszeiten von Query Alpha und Query Beta nahe beieinander. Die folgende Abfrage gibt den Status der automatischen Plankorrektur zurück.

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'

Außerdem finden wir einige grafische Informationen in Abfragen mit erzwungenen Plänen . Dieses Diagramm definiert die erzwungenen Abfragepläne und Abfragen.

Referenzen

Automatische Plankorrektur in SQL Server 2017

Kardinalitätsschätzung