En este artículo, examinaremos las configuraciones del ámbito de la base de datos y la corrección automática del plan de SQL Server 2017. Microsoft agregó nuevas funciones a SQL Server 2017 que mejoraron el rendimiento de las consultas.
El rendimiento de las consultas de SQL Server está relacionado con la calidad y la precisión del plan de ejecución. Cuando ejecutamos una consulta, el optimizador de consultas analiza una gran cantidad de planes de ejecución y luego decide cuál es el plan de ejecución de consulta óptimo.
Estimación de cardinalidad heredada: El Estimador de cardinalidad predice cuántas filas devolverá la consulta y determina la asignación de memoria de la consulta.
En SQL Server 2017, la versión predeterminada del modelo de estimación de cardinalidad es 14.0, pero si desea utilizar la versión anterior 7.0 del Estimador de cardinalidad, puede hacerlo cambiando la opción Estimación de cardinalidad heredada en Configuraciones de ámbito de base de datos sección.
El valor predeterminado de la estimación de cardinalidad heredada es APAGADO. Por lo tanto, si desea utilizar la versión anterior, debe activarla.
Alternativamente, puede cambiar esta propiedad en T-SQL.
ALTER DATABASE SCOPED CONFIGURATION SET LEGACY_CARDINALITY_ESTIMATION = OFF|ON;
Sin embargo, si habilita esta configuración, afectará a todas las consultas. Como resultado, esto puede dañar el rendimiento de la consulta. Para evitar esto, puede usar la sugerencia FORCE_LEGACY_CARDINALITY_ESTIMATION.
Cuando ejecutemos esta consulta en la base de datos de WideWorldImporters, utilizará automáticamente una nueva versión de la estimación de cardinalidad.
SELECT [o].[CustomerID], o.LastEditedBy , [o].[OrderDate] FROM Sales.Orders o WHERE [o].[OrderDate] >= '20140101'
Cuando agregamos FORCE_LEGACY_CARDINALITY_ESTIMATION a la consulta, el optimizador de consultas usará la versión anterior o más antigua de la estimación de cardinalidad.
MAXDOP
La sugerencia de consulta MAXDOP nos permite ejecutar consultas en paralelo.
ALTER DATABASE SCOPED CONFIGURATION SET MAXDOP = 4; GO
Análisis de parámetros: Cuando el tiempo de ejecución de una consulta cambia drásticamente y este cambio de tiempo está relacionado con el parámetro de consulta, se denomina detección de parámetros.
Ahora, crearemos un procedimiento almacenado en la base de datos AdventureWorks. Enviaremos diferentes parámetros y compararemos los planes de ejecución.
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
Como se muestra en la imagen a continuación, SQL Server genera un plan de ejecución diferente para la misma consulta. El plan de ejecución de Query Mars recomienda un índice. El parámetro de consulta cambia el plan de ejecución óptimo.
Ejecute esta consulta y observe los planes de ejecución.
DBCC FREEPROCCACHE --Query Mars EXEC Get_OrderID_OrderQty @ProductID=870 --Query Venus EXEC Get_OrderID_OrderQty @ProductID=897
El plan de ejecución de Query Venus es el mismo que el plan de ejecución de Query Mars. Este es el rastreo de parámetros porque el plan de ejecución en caché se compila para el plan de ejecución de Query Mars. Por este motivo, Query Venus utiliza el mismo plan de ejecución.
Ahora, deshabilitaremos el rastreo de parámetros y ejecutaremos las mismas consultas.
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
Examinemos:
El optimizador de consultas de SQL Server generó el plan de ejecución óptimo para Query Venus y Query Mars. Este enfoque proporciona el rendimiento óptimo a la consulta.
Hay algunas opciones para evitar este problema:
- OPCIÓN(RECOMPILAR)
- OPCIÓN (OPTIMIZAR PARA(@VARIABLE=DESCONOCIDO))
Corrección automática de planes
SQL Server 2017 incluye una nueva función llamada Corrección automática de planes. Cuando ejecutamos una consulta, el optimizador de consultas crea un plan de ejecución. Por alguna razón, el optimizador de consultas elige planes de ejecución incorrectos. Algunas de las razones son las siguientes:
- Una consulta que no cumple con los criterios de rendimiento
- Estadísticas desactualizadas
- Índices inadecuados
Cuando el optimizador de consultas de SQL Server decide cambiar el plan de ejecución y este plan de ejecución daña el rendimiento, el rendimiento de la consulta se denomina regresión del plan. Una nueva función viene con SQL Server 2016. Esta herramienta ayuda a monitorear y solucionar problemas de rendimiento de consultas y, al mismo tiempo, almacena métricas de rendimiento y contadores de la ejecución de consultas.
Podemos habilitar estas opciones en las propiedades de la base de datos.
Ahora, vamos a hacer una demostración de esta función. En primer lugar, borre la caché de procedimientos y cree un procedimiento almacenado.
/**************************************** 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
En este paso, ejecutaremos este procedimiento con diferentes parámetros y encontraremos la diferencia de tiempo de ejecución.
--Query Alpha DBCC FREEPROCCACHE EXEC Test_CoddingSight2 7 GO 80 DBCC FREEPROCCACHE EXEC Test_CoddingSight2 -1 --Query Beta EXEC Test_CoddingSight2 7 GO 80
Como puede ver, la primera consulta se completó en 12 segundos, mientras que la segunda se realizó en 33 segundos. El motivo de esta gran diferencia es que el optimizador de consultas elige un plan de ejecución inadecuado para Query Beta.
Comparemos los planes de ejecución de Query Alpha y Query Beta.
Plan de ejecución de Query Alpha
Plan de ejecución de Query Beta
En las imágenes de arriba, el optimizador de consultas crea diferentes planes de ejecución para la misma consulta. Cuando observamos las consultas que más consumen recursos , podemos ver que Query Beta consume más recursos que Query Alpha.
La siguiente consulta devolverá información detallada sobre las recomendaciones de ajuste.
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 columna de razones muestra por qué tenemos que aplicar esta recomendación.
Ahora, volveremos a ejecutar Query Alpha y Query Beta con la corrección automática del plan habilitada.
/**************************************** 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
Después de esta demostración, el plan de ejecución de Query Alpha se aplica a Query Beta. Además, los tiempos de ejecución de Query Alpha y Query Beta son similares. La siguiente consulta devolverá el estado de corrección automática del plan.
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'
Además, podemos encontrar información gráfica en Consultas con Planes Forzados . Este gráfico define los planes de consulta forzada y la consulta.
Referencias
Corrección automática de planes en SQL Server 2017
Estimación de Cardinalidad