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

Configurazioni con ambito database di SQL Server e correzione automatica del piano

In questo articolo esamineremo le configurazioni con ambito database e la correzione automatica del piano di SQL Server 2017. Microsoft ha aggiunto nuove funzionalità a SQL Server 2017 che hanno migliorato le prestazioni delle query.

Le prestazioni delle query di SQL Server sono correlate alla qualità e all'accuratezza del piano di esecuzione. Quando eseguiamo una query, Query Optimizer analizza molti piani di esecuzione e quindi decide il piano di esecuzione della query ottimale.

Stima della cardinalità dell'eredità: Lo stimatore di cardinalità prevede il numero di righe restituite dalla query e determina l'allocazione di memoria della query.

In SQL Server 2017, la versione predefinita del modello di stima della cardinalità è 14.0, ma se si desidera utilizzare la versione precedente 7.0 dello strumento per la stima della cardinalità, è possibile farlo modificando l'opzione di stima della cardinalità legacy in Configurazioni con ambito database sezione.

Il valore predefinito della stima della cardinalità legacy è OFF. Pertanto, se desideri utilizzare la versione precedente, devi attivarla.

In alternativa, puoi modificare questa proprietà in T-SQL.

ALTER DATABASE
    SCOPED CONFIGURATION  
        SET LEGACY_CARDINALITY_ESTIMATION = OFF|ON;

Tuttavia, se abiliti questa impostazione, influirà su tutte le query. Di conseguenza, ciò potrebbe danneggiare le prestazioni della query. Per evitarlo, puoi utilizzare il suggerimento FORCE_LEGACY_CARDINALITY_ESTIMATION.

Quando eseguiamo questa query nel database WideWorldImporters, utilizzerà automaticamente una nuova versione della stima della cardinalità.

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

FROM Sales.Orders o

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

Quando aggiungiamo FORCE_LEGACY_CARDINALITY_ESTIMATION alla query, Query Optimizer utilizzerà la versione precedente o meno recente della stima della cardinalità.

MAXDOP : possiamo impostare il massimo grado di parallelismo per un singolo database. Prima che questa funzionalità fosse creata, potevamo solo configurare il livello del server MAXDOP.

L'hint di query MAXDOP ci consente di eseguire query in parallelo.

ALTER DATABASE  SCOPED CONFIGURATION 
 SET MAXDOP = 4;
 GO

Sniffing dei parametri: Quando il tempo di esecuzione di una query cambia drasticamente e questa modifica è correlata al parametro della query, si parla di sniffing del parametro.

Ora creeremo una stored procedure nel database AdventureWorks. Invieremo parametri diversi e confronteremo i piani di esecuzione.

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

Come mostrato nell'immagine seguente, SQL Server genera un piano di esecuzione diverso per la stessa query. Il piano di esecuzione di Query Mars consiglia un indice. Il parametro query modifica il piano di esecuzione ottimale.

Esegui questa query e guarda i piani di esecuzione.

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

--Query Venus
EXEC Get_OrderID_OrderQty @ProductID=897

Il piano di esecuzione di Query Venus è lo stesso del piano di esecuzione di Query Mars. Questo è lo sniffing dei parametri perché il piano di esecuzione memorizzato nella cache viene compilato per il piano di esecuzione di Query Mars. Per questo motivo, Query Venus utilizza lo stesso piano di esecuzione.

Ora disabiliteremo lo sniffing dei parametri ed eseguiremo le stesse query.

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

Esaminiamo:

L'ottimizzatore di query di SQL Server ha generato il piano di esecuzione ottimale per Query Venus e Query Mars. Questo approccio fornisce le prestazioni ottimali alla query.

Ci sono alcune opzioni per evitare questo problema:

  • OPZIONE(RICIMPILA)
  • OPZIONE (OTTIMIZZA PER(@VARIABLE=SCONOSCIUTO))

Correzione automatica del piano

SQL Server 2017 include una nuova funzionalità denominata Correzione automatica del piano. Quando eseguiamo una query, Query Optimizer crea un piano di esecuzione. Per alcuni motivi, Query Optimizer sceglie piani di esecuzione errati. Alcuni dei motivi sono i seguenti:

  • Una query che non soddisfa i criteri di prestazione
  • Statistiche non aggiornate
  • Indici non idonei

Quando Query Optimizer di SQL Server decide di modificare il piano di esecuzione e questo piano di esecuzione danneggia le prestazioni, le prestazioni della query vengono chiamate regressione del piano. Una nuova funzionalità viene fornita con SQL Server 2016. Questo strumento aiuta a monitorare e risolvere i problemi delle prestazioni delle query e allo stesso tempo archivia le metriche delle prestazioni e i contatori dell'esecuzione della query.

Possiamo abilitare queste opzioni nelle proprietà del database.

Ora faremo una demo di questa funzione. Prima di tutto, svuota la cache delle procedure e crea una stored 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

A questo punto, eseguiremo questa procedura con parametri diversi e troveremo la differenza di tempo di esecuzione.

--Query Alpha
DBCC FREEPROCCACHE 
EXEC Test_CoddingSight2 7
GO 80

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

Come puoi vedere, la prima query è stata completata in 12 sec, mentre la seconda è stata eseguita in 33 sec. Il motivo di questa notevole differenza è che Query Optimizer sceglie un piano di esecuzione non adatto per Query Beta.

Confrontiamo i piani di esecuzione di Query Alpha e Query Beta.

Piano di esecuzione di Query Alpha

Piano di esecuzione di Query Beta

Nelle immagini sopra, Query Optimizer crea piani di esecuzione diversi per la stessa query. Quando esaminiamo le query che consumano risorse principali , possiamo vedere che Query Beta consuma più risorse di Query Alpha.

La query seguente restituirà informazioni dettagliate sui consigli di ottimizzazione.

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'

La colonna del motivo mostra perché dobbiamo applicare questo consiglio.

Ora, eseguiremo nuovamente Query Alpha e Query Beta con la correzione automatica del piano abilitata.

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

Dopo questa demo, il piano di esecuzione di Query Alpha viene applicato a Query Beta. Inoltre, i tempi di esecuzione di Query Alpha e Query Beta sono vicini l'uno all'altro. La query seguente restituirà lo stato di correzione automatica del piano.

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'

Inoltre, possiamo trovare alcune informazioni grafiche in Query con piani forzati . Questo grafico definisce i piani di query forzati e la query.

Riferimenti

Correzione automatica del piano in SQL Server 2017

Stima della cardinalità