Estadísticas

Se aplica a: SQL Server 2022 (16.x) Azure SQL DatabaseAzure SQL Managed Instance

El Optimizador de consultas utiliza estadísticas para crear planes de consulta que mejoren el rendimiento de las consultas. En el caso de la mayoría de las consultas, el Optimizador de consultas ya genera las estadísticas necesarias para un plan de consulta de alta calidad. En algunos casos, para obtener los mejores resultados, es necesario crear estadísticas adicionales o modificar el diseño de la consulta. En este artículo se explican los conceptos relativos a la estadística y se proporcionan directrices para emplear la estadística de optimización de consultas de forma eficaz.

Componentes y conceptos

Estadísticas

Las estadísticas para la optimización de consulta son objetos binarios grandes (BLOB) que contienen información estadística sobre la distribución de valores en una o más columnas de una tabla o vista indizada. El Optimizador de consultas utiliza estas estadísticas para estimar la cardinalidad, es decir, el número de filas, en el resultado de la consulta. Estas estimaciones de cardinalidad permiten al Optimizador de consultas crear un plan de consulta de alta calidad. Por ejemplo, en función de los predicados, el Optimizador de consultas podría usar las estimaciones de cardinalidad para elegir el operador Index Seek en lugar del operador Index Scan, que requiere un uso intensivo de los recursos, si eso mejora el rendimiento de la consulta.

Cada objeto de estadísticas se crea en una lista de una o más columnas de la tabla e incluye un histograma que muestra la distribución de valores en la primera columna. Los objetos de estadísticas en varias columnas también almacenan la información estadística relativa a la correlación de valores entre las columnas. Estas estadísticas de la correlación, o densidades, derivan del número de filas distintas de valores de columna.

Histograma

Un histograma mide la frecuencia de aparición de cada valor distinto en un conjunto de datos. El optimizador de consultas calcula un histograma sobre los valores de la primera columna de clave del objeto de estadísticas; para ello, selecciona los valores de la columna tomando una muestra estadística de las filas o realizando un examen completo de todas las filas de la tabla o vista. Si el histograma se crea a partir de muestras de un conjunto de filas, los totales almacenados para el número de filas y el número de valores distintos son las estimaciones y no es necesario que sean números enteros.

Nota:

Los histogramas de SQL Server solo se crean para una única columna: la primera del conjunto de columnas de clave del objeto de estadísticas.

Para crear el histograma, el optimizador de consultas ordena los valores de la columna, calcula el número de valores que coinciden con cada valor distinto de esta y, luego, agrega los valores de la columna en 200 pasos contiguos del histograma como máximo. Cada paso del histograma incluye un rango de valores de columna seguido de un valor de columna de límite superior. El intervalo incluye todos los valores de columna posibles comprendidos entre los valores límite (sin incluir los propios valores límite). El valor de columna ordenado más pequeño es el valor del límite superior del primer paso del histograma.

Más concretamente, SQL Server crea el histograma del conjunto ordenado de valores de columna en tres pasos:

  • Inicialización del histograma: en el primer paso, se procesa una secuencia de valores desde el principio del conjunto ordenado y se recopila un máximo de 200 valores de range_high_key, equal_rows, range_rows y distinct_range_rows (range_rows y distinct_range_rows son siempre cero durante este paso). El primer paso finaliza cuando se han agotado todas las entradas o cuando se han encontrado 200 valores.
  • Examen con combinación de depósito: cada valor adicional de la columna inicial de la clave de estadísticas se procesa en el segundo paso, de forma ordenada; cada valor sucesivo se agrega al último rango o se crea un rango nuevo al final (esto es posible porque los valores de entrada están ordenados). Si se crea un rango nuevo, un par de rangos existentes colindantes se contrae en un solo rango. Este par de rangos se selecciona para minimizar la pérdida de información. Este método usa un algoritmo de diferencias máximas para minimizar el número de pasos del histograma a la vez que maximiza las diferencias entre los valores de límite. El número de pasos después de contraer los rangos permanece en 200 a lo largo de este paso.
  • Consolidación del histograma: en el tercer paso, es posible que se contraigan más rangos si no se pierde una cantidad significativa de información. El número de pasos del histograma puede ser menor que el número de valores distintos, incluso para las columnas con menos de 200 puntos de límite. Por lo tanto, incluso aunque la columna tenga más de 200 valores únicos, es posible que el histograma tenga menos de 200 pasos. Para una columna formada solamente por valores únicos, el histograma consolidado tendrá un mínimo de tres pasos.

Nota:

Si se ha generado el histograma con un ejemplo en lugar de hacerlo mediante fullscan, los valores de equal_rows, range_rows, distinct_range_rows y average_range_rows son estimados y, por tanto, no es necesario que sean números enteros.

En el diagrama siguiente se muestra un histograma con seis pasos. El área a la izquierda del primer valor límite superior es el primer paso.

Image of how a histogram is calculated from sampled column values.

En cada paso del histograma anterior:

  • La línea gruesa representa el valor de límite superior (range_high_key) y el número de veces que tiene lugar (equal_rows).

  • El área de color sólido situada a la izquierda de range_high_key representa el rango de valores de columna y el número medio de veces que tiene lugar cada valor de columna (average_range_rows). El valor de average_range_rows en el primer paso del histograma siempre es 0.

  • Las líneas de puntos representan los valores de las muestras utilizados para estimar el número total de valores distintos que hay en el rango (distinct_range_rows) y el número total de valores que hay en el rango (range_rows). El optimizador de consultas utiliza range_rows y distinct_range_rows para calcular average_range_rows y no almacena los valores de las muestras.

Vector de densidad

Densidad es la información sobre el número de duplicados en una determinada columna o combinación de columnas, y se calcula como 1/(número de valores distintos). El optimizador de consultas utiliza las densidades para mejorar las estimaciones de cardinalidad de las consultas que devuelven varias columnas de la misma tabla o vista indexada. A medida que disminuye la densidad, aumenta la selectividad de un valor. Por ejemplo, en una tabla que representa automóviles, muchos automóviles tienen el mismo fabricante, pero cada uno dispone de un único número de identificación de vehículo (NIV). Un índice del NIV es más selectivo que un índice del fabricante, porque NIV tiene una densidad inferior a la del fabricante.

Nota:

Frecuencia es la información sobre la aparición de cada valor distinto en la primera columna de clave del objeto de estadísticas y se calcula como el recuento de filas * densidad. Puede encontrarse una frecuencia máxima de 1 en las columnas con valores únicos.

El vector de densidad contiene una densidad para cada prefijo de columnas del objeto de estadísticas. Por ejemplo, si un objeto de estadísticas tiene las columnas de clave CustomerId, ItemId y Price, la densidad se calcula en cada uno de los siguientes prefijos de columna.

Prefijo de columna Densidad calculada en
(CustomerId) Filas con valores que se corresponden con CustomerId
(CustomerId, ItemId) Filas con valores que se corresponden con CustomerId y ItemId
(CustomerId, ItemId, Price) Filas con valores que se corresponden con CustomerId, ItemId y Price

Estadísticas filtradas

Las estadísticas filtradas pueden mejorar el rendimiento de las consultas que se seleccionan desde subconjuntos de datos bien definidos. Las estadísticas filtradas utilizan un predicado de filtro para seleccionar el subconjunto de datos que se incluye en las estadísticas. Las estadísticas filtradas bien diseñadas pueden mejorar el plan de ejecución de la consulta en comparación con las estadísticas de tabla completa. Para obtener más información sobre el predicado de filtro, consulte CREATE STATISTICS (Transact-SQL). Para obtener más información sobre los casos en los que conviene crear estadísticas filtradas, consulte la sección Cuándo crear las estadísticas de este artículo.

Opciones de estadísticas

Hay opciones que afectan al momento y al modo en los que se crean y actualizan las estadísticas. Estas opciones se pueden configurar únicamente en el nivel de la base de datos.

Opción AUTO_CREATE_STATISTICS

Cuando está activada la opción automática de creación de estadísticas, AUTO_CREATE_STATISTICS, el optimizador de consultas crea las estadísticas en columnas individuales en el predicado de consulta, según sea necesario, para mejorar las estimaciones de cardinalidad para el plan de consulta. Estas estadísticas de columna única se crean en las columnas que aún no tienen un histograma en un objeto de estadísticas existente. La opción AUTO_CREATE_STATISTICS no determina si las estadísticas se crean para los índices. Esta opción tampoco genera estadísticas filtradas. Se aplica estrictamente a estadísticas de columna única para la tabla completa.

Cuando el Optimizador de consultas crea las estadísticas como resultado de usar la opción AUTO_CREATE_STATISTICS, el nombre de las estadísticas comienza con _WA. Puede utilizar la consulta siguiente para determinar si el Optimizador de consultas ha creado estadísticas para una columna de predicado de consulta.

SELECT OBJECT_NAME(s.object_id) AS object_name,
    COL_NAME(sc.object_id, sc.column_id) AS column_name,
    s.name AS statistics_name
FROM sys.stats AS s
INNER JOIN sys.stats_columns AS sc
    ON s.stats_id = sc.stats_id AND s.object_id = sc.object_id
WHERE s.name like '_WA%'
ORDER BY s.name;

Opción AUTO_UPDATE_STATISTICS

Cuando está activada la opción automática de actualización de estadísticas, AUTO_UPDATE_STATISTICS, el optimizador de consultas determina cuándo las estadísticas pueden quedar obsoletas y las actualiza cuando una consulta las usa. Esta acción también se conoce como recompilación de estadísticas. Las estadísticas se vuelven obsoletas después de que operaciones de inserción, actualización, eliminación o combinación cambien la distribución de los datos en la tabla o la vista indexada. El optimizador de consultas determina cuándo las estadísticas podrían quedar obsoletas; para ello, se cuenta el número de modificaciones de filas desde la actualización más reciente de las estadísticas y se compara el número de modificaciones de filas con un umbral. El umbral se basa en la cardinalidad de la tabla, que se puede definir como el número de filas de la tabla o la vista indexada.

Marcar las estadísticas como no actualizadas en función de las modificaciones de las filas ocurre incluso cuando la opción AUTO_UPDATE_STATISTICS está desactivada. Cuando la opción AUTO_UPDATE STATISTICS está desactivada, no se actualizan las estadísticas incluso cuando están marcadas como no actualizadas. Los planes seguirán usando los objetos de estadísticas no actualizados. Establecer la opción AUTO_UPDATE_STATISTICS en OFF puede generar planes de consulta poco óptimos y un rendimiento degradado de las consultas. Se recomienda establecer la opción AUTO_UPDATE STATISTICS en ON.

  • Hasta SQL Server 2014 (12.x), el motor de base de datos usa un umbral de recompilación basado en el número de filas de la tabla o la vista indexada en el momento en que se evaluaron las estadísticas. El umbral es diferente si una tabla es temporal o permanente.

    Tipo de tabla Cardinalidad de la tabla (n) Umbral de recompilación (n.º de modificaciones)
    Temporales n< 6 6
    Temporales 6 <= n<= 500 500
    Permanente n<= 500 500
    Temporal o permanente n> 500 500 + (0.20 * n)

    Por ejemplo, si la tabla contiene 20 000 filas, el cálculo es 500 + (0.2 * 20,000) = 4,500 y las estadísticas se actualizarán cada 4500 modificaciones.

  • A partir de SQL Server 2016 (13.x) y en el nivel de compatibilidad de la base de datos 130, el motor de base de datos también usa un umbral de recompilación de estadísticas dinámico y decreciente que se ajusta según la cardinalidad de la tabla en el momento en que se evaluaron las estadísticas. Con este cambio, las estadísticas en tablas de gran tamaño se actualizarán con más frecuencia. Sin embargo, si una base de datos tiene un nivel de compatibilidad inferior a 130, se aplica el umbral de SQL Server 2014 (12.x).

    Tipo de tabla Cardinalidad de la tabla (n) Umbral de recompilación (n.º de modificaciones)
    Temporales n< 6 6
    Temporales 6 <= n<= 500 500
    Permanente n<= 500 500
    Temporal o permanente n> 500 MIN ( 500 + (0,20 * n), SQRT(1000 * n) )

    Por ejemplo, si la tabla contiene 2 millones de filas, entonces, el cálculo es el valor mínimo de 500 + (0.20 * 2,000,000) = 400,500 y SQRT(1,000 * 2,000,000) = 44,721. Esto significa que las estadísticas se actualizarán cada 44 721 modificaciones.

Importante

En SQL Server 2008 R2 (10.50.x) a SQL Server 2014 (12.x) o en SQL Server 2016 (13.x) y versiones posteriores en el nivel de compatibilidad de la base de datos 120 y versiones posteriores, habilite la marca de seguimiento 2371 para que SQL Server use un umbral de actualización de estadísticas dinámicas decreciente.

Aunque se recomienda en todos los escenarios, la habilitación de la marca de seguimiento 2371 es opcional. Sin embargo, puede usar la siguiente guía para habilitar la marca de seguimiento 2371 en su ambiente anterior a SQL Server 2016 (13.x):

  • Si está en un sistema SAP, habilite este seguimiento. Para más información, consulte este blog sobre la marca de seguimiento 2371.
  • Si tiene que depender del trabajo nocturno para actualizar las estadísticas porque la actualización automática actual no se desencadena con la frecuencia suficiente, considere la posibilidad de habilitar la marca de seguimiento 2371 para ajustar el umbral a la tabla de cardinalidad.

El Optimizador de consultas comprueba que hay estadísticas obsoletas antes de compilar una consulta y antes de ejecutar un plan de consulta almacenado en la memoria caché. Antes de compilar una consulta, el Optimizador de consultas utiliza las columnas, tablas y vistas indexadas en el predicado de consulta para determinar qué estadísticas podrían estar obsoletas. Antes de ejecutar un plan de consulta almacenado en caché, Motor de base de datos comprueba que el plan de consulta haga referencia a las estadísticas actualizadas.

La opción AUTO_UPDATE_STATISTICS se aplica a los objetos de estadísticas creados para los índices, columnas únicas de predicados de consulta y las estadísticas creadas con la instrucción CREATE STATISTICS . Esta opción también se aplica a las estadísticas filtradas.

Puede usar sys.dm_db_stats_properties para realizar un seguimiento de forma precisa del número de filas cambiadas en una tabla y decidir si desea actualizar las estadísticas manualmente.

AUTO_UPDATE_STATISTICS siempre es OFF para las tablas optimizadas para memoria

AUTO_UPDATE_STATISTICS_ASYNC

La opción de actualización asincrónica de estadísticas AUTO_UPDATE_STATISTICS_ASYNC determina si el optimizador de consultas usa actualizaciones sincrónicas o asincrónicas de las estadísticas. La opción de actualización asincrónica de las estadísticas está desactivada de forma predeterminada y el optimizador de consultas actualiza las estadísticas sincrónicamente. La opción AUTO_UPDATE_STATISTICS_ASYNC se aplica a los objetos de estadísticas creados para índices y columnas únicas de los predicados de consulta, así como a las estadísticas creadas con la instrucción CREATE STATISTICS .

Nota:

Para establecer la opción de actualización asincrónica de las estadísticas en SQL Server Management Studio, en la página Opciones de la ventana Propiedades de la base de datos, las opciones Actualizar estadísticas automáticamente y Actualizar estadísticas automática y asincrónicamente deben establecerse en True.

Las actualizaciones de las estadísticas pueden ser sincrónicas (el valor predeterminado) o asincrónicas.

  • Con las actualizaciones sincrónicas de las estadísticas, las consultas siempre se compilan y ejecutan con estadísticas actualizadas. Si las estadísticas no están actualizadas, el optimizador de consultas esperará a que lo estén antes de compilar y ejecutar la consulta.

  • En el caso de las actualizaciones asincrónicas de las estadísticas, las consultas se compilan con estadísticas existentes, incluso aunque estas no estén actualizadas. Si, al compilar la consulta, las estadísticas no están actualizadas, el optimizador de consultas podría elegir un plan de consultas poco óptimo. Las estadísticas suelen actualizarse poco después. Las consultas que se compilen tras completarse las actualizaciones de las estadísticas se beneficiarán del hecho de poder usar estadísticas actualizadas.

Considere la posibilidad de usar las estadísticas sincrónicas al realizar las operaciones que cambian la distribución de los datos, como truncar una tabla o realizar una actualización masiva de un gran porcentaje de las filas. Si no actualiza manualmente las estadísticas después de finalizar la operación, el uso de estadísticas sincrónicas garantizará que las estadísticas estén actualizadas antes de ejecutar las consultas en los datos modificados.

Considere el uso de estadísticas asincrónicas para lograr tiempos de respuesta a la consulta más predecibles en los escenarios siguientes:

  • Su aplicación ejecuta frecuentemente la misma consulta, consultas similares o los planes de consulta almacenados en memoria caché similares. Sus tiempos de respuesta a la consulta podrían ser más predecibles con actualizaciones asincrónicas de las estadísticas que con actualizaciones sincrónicas, porque el Optimizador de consultas puede ejecutar las consultas de entrada sin esperar a que las estadísticas se actualicen. Esto evita que se retrasen algunas consultas, pero no otras.

  • Su aplicación ha experimentado tiempos de espera de solicitud de cliente causados por una o varias consultas que aguardaban la actualización de estadísticas. En algunos casos, la espera por las estadísticas sincrónicas podría causar errores en aplicaciones con tiempos de espera agresivos.

Nota:

Las estadísticas de las tablas temporales locales siempre se actualizan de forma sincrónica, independientemente de la opción AUTO_UPDATE_STATISTICS_ASYNC. Las estadísticas de las tablas temporales globales se actualizan de forma sincrónica o asincrónica, según la opción AUTO_UPDATE_STATISTICS_ASYNC establecida para la base de datos de usuario.

La actualización asincrónica de las estadísticas se realiza mediante una solicitud en segundo plano. Cuando la solicitud está lista para escribir estadísticas actualizadas en la base de datos, intenta adquirir un bloqueo de modificación del esquema en el objeto de metadatos de estadísticas. Si una sesión diferente ya mantiene un bloqueo en el mismo objeto, la actualización asincrónica de las estadísticas se bloqueará hasta que se pueda adquirir el bloqueo de modificación del esquema. Del mismo modo, las sesiones que deban adquirir un bloqueo de estabilidad de esquema (Sch-S) en el objeto de metadatos de estadísticas para compilar una consulta pueden quedar bloqueadas por la sesión en segundo plano de actualización de estadísticas, que ya contiene el bloqueo de modificación de esquema o está a la espera de adquirirlo. Por lo tanto, para las cargas de trabajo con compilaciones de consultas muy frecuentes y las actualizaciones frecuentes de las estadísticas, el uso de estadísticas asincrónicas puede aumentar la probabilidad de que se produzcan incidencias de simultaneidad debido a los bloqueos.

En Azure SQL Database, Azure SQL Managed Instance y empezando con SQL Server 2022 (16.x), puede evitar posibles incidencias de simultaneidad mediante la actualización asincrónica de las estadísticas. Para ello, habilite la configuración de ámbito de la base de datos ASYNC_STATS_UPDATE_WAIT_AT_LOW_PRIORITY. Con esta configuración habilitada, la solicitud en segundo plano esperará a adquirir el bloqueo de modificación de esquema (Sch-M) y conservará las estadísticas actualizadas en una cola independiente de prioridad baja, lo que permitirá que otras solicitudes sigan compilando consultas con las estadísticas existentes. Cuando ninguna otra sesión mantenga un bloqueo en el objeto de metadatos de estadísticas, la solicitud en segundo plano adquirirá el bloqueo de modificación del esquema y la actualización de estadísticas. En el caso improbable de que la solicitud en segundo plano no pueda adquirir el bloqueo en un período de tiempo de expiración de varios minutos, se anulará la actualización asincrónica de las estadísticas y estas no se actualizarán hasta que se desencadene otra actualización automática de las estadísticas o se actualicen manualmente.

Nota:

La opción de configuración del ámbito de la base de datos ASYNC_STATS_UPDATE_WAIT_AT_LOW_PRIORITY ahora está disponible en Azure SQL Database, Azure SQL Managed Instance y en SQL Server empezando con SQL Server 2022 (16.x).

Opción AUTO_DROP

Se aplica a*: Azure SQL Database, Azure SQL Managed Instance y a partir de SQL Server 2022 (16.x)

En versiones de SQL Server anteriores a SQL Server 2022 (16.x), si un usuario crea estadísticas manualmente o si se crean con una herramienta de terceros en una base de datos de usuario, esos objetos de estadísticas pueden bloquear o interferir con los cambios de esquema que el cliente puede desear.

A partir de SQL Server 2022 (16.x), la opción auto drop está habilitada de manera predeterminada en todas las bases de datos nuevas y migradas. La propiedad AUTO_DROP permite la creación de objetos de estadísticas en un modo tal que el objeto estadístico no bloquee un cambio de esquema posterior, sino que las estadísticas se quitarán según sea necesario. De esta manera, las estadísticas creadas manualmente con auto drop habilitado se comportan como las estadísticas creadas automáticamente.

Nota:

Si se intenta establecer o anular la propiedad auto drop en las estadísticas creadas automáticamente, se pueden producir errores. Las estadísticas creadas automáticamente siempre usan la eliminación automática. Algunas copias de seguridad, cuando se restauran, pueden tener esta propiedad establecida incorrectamente hasta la próxima vez que se actualice el objeto de estadísticas (manual o automáticamente). Sin embargo, las estadísticas creadas automáticamente siempre se comportan como estadísticas de eliminación automática. Al restaurar una base de datos en SQL Server 2022 (16.x) desde una versión anterior, se recomienda ejecutar sp_updatestats en la base de datos y establecer los metadatos adecuados para la característica de eliminación automática de las estadísticas.

Por ejemplo, para crear manualmente un objeto de estadísticas en la tabla dbo.DatabaseLog:

CREATE STATISTICS [mystats] ON [dbo].[DatabaseLog]([DatabaseLogID], [PostTime], [DatabaseUser]) WITH AUTO_DROP = ON;

Por ejemplo, para actualizar una configuración de colocación automática del objeto de estadísticas en la tabla dbo.DatabaseLog:

UPDATE STATISTICS [dbo].[DatabaseLog] [mystats] WITH AUTO_DROP = ON;

Para evaluar la configuración de eliminación automática en las estadísticas existentes, use la columna auto_drop en sys.stats:

SELECT object_id, [name], auto_drop
FROM sys.stats;

Para más información, consulte CREATE STATISTICS (Transact-SQL).

INCREMENTAL

Válido para : SQL Server 2014 (12.x) y versiones posteriores.

Cuando la opción INCREMENTAL de CREATE STATISTICS está establecida en ON, se generan estadísticas por partición. Cuando se establece en OFF, se quita el árbol de estadísticas y SQL Server recalcula las estadísticas. El valor predeterminado es OFF. Este valor invalida la propiedad INCREMENTAL de la base de datos. Para obtener más información sobre cómo crear estadísticas incrementales, consulte CREATE STATISTICS (Transact-SQL). Para obtener más información sobre cómo crear estadísticas por partición automáticamente, consulte Propiedades de la base de datos (Página Opciones) y Opciones de ALTER DATABASE SET (Transact-SQL).

Cuando se agregan particiones a una tabla grande, las estadísticas deben actualizarse para que incluyan las particiones nuevas. Sin embargo, el tiempo necesario para examinar la tabla completa (opción FULLSCAN o SAMPLE) puede ser bastante largo. Además, no es necesario examinar toda la tabla porque puede que solo se necesiten las estadísticas de las particiones nuevas. La opción incremental crea y almacena estadísticas sobre cada partición y, cuando se actualiza, solo actualiza las estadísticas de las particiones que necesitan estadísticas nuevas.

Si no se admiten las estadísticas por partición, la opción se omite y se genera una advertencia. Las estadísticas incrementales no se admiten para los siguientes tipos de estadísticas:

  • Estadísticas creadas con índices que no están alineados por partición con la tabla base.
  • Estadísticas creadas sobre bases de datos secundarias legibles AlwaysOn.
  • Estadísticas creadas sobre bases de datos de solo lectura.
  • Estadísticas creadas sobre índices filtrados.
  • Estadísticas creadas sobre vistas.
  • Estadísticas creadas sobre tablas internas.
  • Estadísticas creadas con índices espaciales o índices XML.

Al crear estadísticas

El Optimizador de consultas ya permite crear las estadísticas de las siguientes formas:

  1. El Optimizador de consultas crea las estadísticas para índices en tablas o vistas cuando se crea el índice. Estas estadísticas se crean en las columnas de clave del índice. Si el índice es un índice filtrado, el Optimizador de consultas crea las estadísticas filtradas en el mismo subconjunto de filas especificado para el índice filtrado. Para obtener más información sobre los índices filtrados, consulte Crear índices filtrados y CREATE INDEX (Transact-SQL).

    Nota:

    A partir de SQL Server 2014 (12.x), las estadísticas no se crean examinando todas las filas de la tabla cuando se crea o se vuelve a compilar un índice con particiones. En su lugar, el Optimizador de consultas usa el algoritmo de muestreo predeterminado para generar estadísticas. Después de actualizar una base de datos con índices con particiones, puede observar una diferencia en los datos del histograma para estos índices. Este cambio de comportamiento puede no afectar al rendimiento de las consultas. Para obtener estadísticas sobre índices con particiones examinando todas las filas de la tabla, use CREATE STATISTICS o UPDATE STATISTICS con la cláusula FULLSCAN.

  2. El optimizador de consultas crea las estadísticas para las columnas únicas de predicados de consulta cuando AUTO_CREATE_STATISTICS está activada.

En la mayoría de las consultas, estos dos métodos de creación de estadísticas aseguran un plan de consulta de alta calidad; en unos casos, puede mejorar los planes de consulta creando estadísticas adicionales con la instrucción CREATE STATISTICS . Estas estadísticas adicionales pueden capturar correlaciones estadísticas que el Optimizador de consultas no tiene en cuenta cuando crea estadísticas para índices o columnas únicas. Su aplicación podría tener las correlaciones estadísticas adicionales en los datos de la tabla que, si se calcula en un objeto de estadísticas, podrían habilitar el Optimizador de consultas para mejorar los planes de consulta. Por ejemplo, las estadísticas filtradas en un subconjunto de filas de datos o las estadísticas de varias columnas en columnas de predicado de consulta podrían mejorar el plan de consulta.

Al crear las estadísticas con la instrucción CREATE STATISTICS, recomendamos mantener la opción AUTO_CREATE_STATISTICS activada para que el Optimizador de consultas continúe creando rutinariamente estadísticas de columna única para las columnas de predicado de consulta. Para obtener más información sobre los predicados de consulta, consulteCondición de búsqueda (Transact-SQL).

Considere la creación de estadísticas con la instrucción CREATE STATISTICS cuando se aplique cualquiera de los escenarios siguientes:

  • El Asistente para la optimización de motor de base de datos sugiere crear las estadísticas.
  • El predicado de consulta contiene varias columnas correlacionadas que ya no están en el mismo índice.
  • La consulta realiza la selección entre un subconjunto de datos.
  • La consulta ha perdido estadísticas.

Nota:

Para obtener información específica de las tablas y estadísticas relacionadas con OLTP en memoria, consulte Estadísticas para las tablas optimizadas para memoria.

Predicado de consulta con varias columnas correlacionadas

Cuando un predicado de consulta contiene varias columnas que tienen relaciones y dependencias entre columnas, las estadísticas sobre esas columnas podrían mejorar el plan de consulta. Las estadísticas sobre varias columnas contienen estadísticas de correlación entre columnas, llamadas densidades, que no están disponibles en las estadísticas de columna única. Las densidades pueden mejorar las estimaciones de cardinalidad cuando los resultados de la consulta dependen de relaciones de los datos entre varias columnas.

Si las columnas ya están en el mismo índice, el objeto de estadísticas de varias columnas ya existe y no es necesario crearlo manualmente. Si las columnas no están ya en el mismo índice, puede crear las estadísticas de varias columnas creando un índice en las columnas o usando la instrucción CREATE STATISTICS. Se necesitan más recursos del sistema para mantener un índice que para mantener un objeto de estadísticas. Si la aplicación no requiere el índice de varias columnas, puede economizar en recursos del sistema creando el objeto de estadísticas sin crear el índice.

Al crear las estadísticas de varias columnas, el orden de las columnas en la definición del objeto de estadísticas afecta a la efectividad de las densidades para realizar las estimaciones de cardinalidad. El objeto de estadísticas almacena las densidades correspondientes a cada prefijo de las columnas de clave en la definición del objeto de estadísticas. Para más información sobre las densidades, vea la sección Densidad en esta página.

Para crear densidades que sean útiles para las estimaciones de cardinalidad, las columnas del predicado de consulta deben coincidir con uno de los prefijos de columnas de la definición del objeto de estadísticas. Por ejemplo, en el siguiente caso se crea un objeto de estadísticas de varias columnas en las columnas LastName, MiddleName y FirstName.

USE AdventureWorks2022;
GO
IF EXISTS (SELECT name FROM sys.stats
    WHERE name = 'LastFirst'
    AND object_ID = OBJECT_ID ('Person.Person'))
DROP STATISTICS Person.Person.LastFirst;
GO
CREATE STATISTICS LastFirst ON Person.Person (LastName, MiddleName, FirstName);
GO

En este ejemplo, el objeto de estadísticas LastFirst tiene densidades para los siguientes prefijos de columna: (LastName), (LastName, MiddleName) y (LastName, MiddleName, FirstName). La densidad no está disponible para (LastName, FirstName). Si la consulta utiliza LastName y FirstName sin utilizar MiddleName, la densidad no está disponible para las estimaciones de cardinalidad.

La consulta realiza la selección entre un subconjunto de datos

Cuando el Optimizador de consultas crea las estadísticas para las columnas únicas e índices, crea las estadísticas para los valores de todas las filas. Cuando las consultas realizan la selección de entre un subconjunto de filas, y ese subconjunto de filas tiene una distribución de datos única, las estadísticas filtradas pueden mejorar los planes de consulta. Puede crear estadísticas filtradas usando la instrucción CREATE STATISTICS con la cláusula WHERE para definir la expresión del predicado de filtro.

Por ejemplo, utilizando AdventureWorks2022, cada producto de la tabla Production.Product pertenece a una de las cuatro categorías de la tabla Production.ProductCategory: Bikes, Components, Clothing y Accessories. Cada una de las categorías tiene una distribución de datos diferente en función del peso: el peso de las bicicletas (bikes) va de 13,77 a 30,0, el de los componentes (components) de 2,12 a 1050,00 con algunos valores NULL, todos los pesos de la ropa (clothing) son NULL, lo mismo que los de los accesorios (accessories).

Utilizando las bicicletas (Bikes) como ejemplo, las estadísticas filtradas para todos los pesos de las bicicletas proporcionarán estadísticas más precisas al Optimizador de consultas y podrán mejorar la calidad del plan de consulta en comparación con las estadísticas de tabla completa o las estadísticas no existentes en la columna del peso (Weight). La columna de peso de bicicleta es una buena candidata para las estadísticas filtradas, pero no necesariamente para un índice filtrado si el número de búsquedas de peso es relativamente pequeño. La ganancia de rendimiento para las búsquedas que proporciona un índice filtrado no podría ser mayor que el mantenimiento adicional y el costo de almacenamiento de agregar un índice filtrado a la base de datos.

La instrucción siguiente crea las estadísticas filtradas BikeWeights en todas las subcategorías de Bikes. La expresión de predicado filtrado define las bicicletas enumerando todas las subcategorías de bicicleta con la comparación Production.ProductSubcategoryID IN (1,2,3). El predicado no puede utilizar el nombre de categoría Bikes porque está almacenado en la tabla Production.ProductCategory, mientras que todas las columnas de la expresión del filtro deben estar en la misma tabla.

USE AdventureWorks2022;
GO
IF EXISTS ( SELECT name FROM sys.stats
    WHERE name = 'BikeWeights'
    AND object_ID = OBJECT_ID ('Production.Product'))
DROP STATISTICS Production.Product.BikeWeights;
GO
CREATE STATISTICS BikeWeights
    ON Production.Product (Weight)
WHERE ProductSubcategoryID IN (1,2,3);
GO

El Optimizador de consultas puede utilizar estadísticas filtradas de BikeWeights para mejorar el plan de consulta correspondiente a la consulta siguiente. Esta segunda selecciona todas las bicicletas cuyo peso es superior a 25.

SELECT P.Weight AS Weight, S.Name AS BikeName
FROM Production.Product AS P
    JOIN Production.ProductSubcategory AS S
    ON P.ProductSubcategoryID = S.ProductSubcategoryID
WHERE P.ProductSubcategoryID IN (1,2,3) AND P.Weight > 25
ORDER BY P.Weight;
GO

Consulta que identifica las estadísticas que faltan

Si un error u otro evento evitan que el Optimizador de consultas cree las estadísticas, el Optimizador de consultas creará el plan de consulta sin utilizar las estadísticas. El Optimizador de consultas marca las estadísticas como perdidas e intenta regenerar las estadísticas la siguiente vez que se ejecuta la consulta.

Las estadísticas perdidas se indican mediante advertencias (el nombre de la tabla aparece en rojo) cuando el plan de ejecución de una consulta se representa gráficamente mediante SQL Server Management Studio. Además, la supervisión de la clase de eventos Missing Column Statistics con SQL Server Profiler indica cuándo se han perdido las estadísticas. Para obtener más información, consulte Categoría de eventos de errores y advertencias (motor de base de datos).

Si se han perdido estadísticas, siga estos pasos:

Cuando faltan las estadísticas de una base de datos de solo lectura o de una instantánea de solo lectura o son obsoletas, motor de base de datos crea y mantiene estadísticas temporales en tempdb. Cuando el motor de base de datos crea estadísticas temporales, el nombre de las estadísticas se anexan con el sufijo _readonly_database_statistic para diferenciar las estadísticas temporales de las permanentes. El sufijo _readonly_database_statistic está reservado para las estadísticas que genera SQL Server. Los scripts para las estadísticas temporales se pueden crear y reproducir en una base de datos de lectura-escritura. Cuando se crea el script, Management Studio cambia el sufijo del nombre de las estadísticas de _readonly_database_statistic a _readonly_database_statistic_scripted.

Solo SQL Server puede crear y actualizar las estadísticas temporales. No obstante, puede eliminar las estadísticas temporales y supervisar las propiedades de estadísticas mediante las mismas herramientas que se usan para las estadísticas permanentes:

  • Elimine las estadísticas temporales con la instrucción DROP STATISTICS.
  • Supervise las estadísticas con las vistas de catálogo sys.stats y sys.stats_columns . La vista de catálogo del sistema sys.stats incluye la columna is_temporary para indicar las estadísticas que son permanentes y las que son temporales.

Debido a que las estadísticas temporales se almacenan en tempdb, el reinicio del servicio SQL Server provoca que desaparezcan todas las estadísticas temporales.

Cuándo actualizar las estadísticas

El Optimizador de consultas determina cuándo las estadísticas podrían quedar obsoletas y, a continuación, las actualiza cuando es necesario para un plan de consulta. En algunos casos, puede mejorar el plan de consulta y, por consiguiente, mejorar su rendimiento. Para ello, puede actualizar las estadísticas con más frecuencia que la que se da cuando la opción AUTO_UPDATE_STATISTICS está activada. Puede actualizar las estadísticas con la instrucción UPDATE STATISTICS o con el procedimiento almacenado sp_updatestats.

La actualización de las estadísticas asegura que las consultas se compilan con estadísticas actualizadas. La actualización de las estadísticas a través de cualquier proceso puede hacer que los planes de consulta se vuelvan a compilar automáticamente. Recomendamos no actualizar las estadísticas de manera manual con demasiada frecuencia, porque hay que elegir el punto válido entre la mejora de los planes de consulta y el tiempo empleado en volver a compilar las consultas. Las compensaciones específicas dependen de su aplicación.

Al actualizar las estadísticas con UPDATE STATISTICS o sp_updatestats, recomendamos mantener activada la opción AUTO_UPDATE_STATISTICS para que el Optimizador de consultas continúe actualizando rutinariamente las estadísticas.

  • Para obtener más información sobre cómo actualizar las estadísticas en una columna, un índice, una tabla o una vista indexada, consulte UPDATE STATISTICS (Transact-SQL).

  • Para obtener más información sobre cómo actualizar las estadísticas para todas las tablas internas y definidas por el usuario de la base de datos, vea el procedimiento almacenado sp_updatestats (Transact-SQL).

  • Para obtener más información sobre los umbrales de las actualizaciones de estadísticas automáticas, consulte Opción AUTO_UPDATE_STATISTICS.

Cuando la opción AUTO_UPDATE_STATISTICS se establece en OFF, todavía puede producirse la recompilación del plan por diversos motivos, pero no ocurrirá automáticamente debido a actualizaciones de estadísticas no actualizadas. Cuando la opción AUTO_UPDATE_STATISTICS se establece en OFF, las actualizaciones de estadísticas solo se producirán a través de otros procesos programados manualmente, como los planes de mantenimiento. Por lo tanto, establecer la opción AUTO_UPDATE_STATISTICS en OFF puede generar planes de consulta poco óptimos y un rendimiento degradado de las consultas.

Detección de estadísticas no actualizadas

Para determinar cuándo se actualizaron por última vez las estadísticas, use las funciones sys.dm_db_stats_properties o STATS_DATE.

Considere la actualización de las estadísticas en las condiciones siguientes:

  • Los tiempos de ejecución de la consulta son lentos.
  • Se producen operaciones de inserción en columnas de clave ascendentes o descendentes.
  • Después de las operaciones de mantenimiento.

Para ejemplos de actualización manual de estadísticas, consulte UPDATE STATISTICS (Transact-SQL).

Tiempos de ejecución de las consultas lentos

Si los tiempos de respuesta de la consulta son lentos o impredecibles, asegúrese de que las consultas tienen estadísticas actualizadas antes de realizar los pasos adicionales de la solución de problemas.

Operaciones de inserción en columnas de clave ascendentes o descendentes

Las estadísticas de columnas de clave ascendentes o descendentes, como IDENTITY o las columnas de marca de tiempo en tiempo real, podrían requerir actualizaciones de las estadísticas más frecuentes que las que realiza el Optimizador de consultas. Las operaciones de inserción anexan nuevos valores a las columnas ascendentes o descendentes. El número de filas agregado podría ser demasiado pequeño para desencadenar una actualización de las estadísticas. Si las estadísticas no están actualizadas y las consultas se seleccionan de las filas recientemente agregadas, las estadísticas actuales no tendrán estimaciones de cardinalidad para estos nuevos valores. Esto puede producir estimaciones de cardinalidad inexactas y un rendimiento lento de las consultas.

Por ejemplo, una consulta que selecciona entre las fechas de pedidos de venta más recientes tendrá estimaciones de cardinalidad inexactas si las estadísticas no se han actualizado para incluir las estimaciones de cardinalidad correspondientes a las fechas de pedidos de venta más recientes.

Después de las operaciones de mantenimiento

Considere la actualización de las estadísticas después de haber realizado procedimientos de mantenimiento que cambian la distribución de los datos, como truncar una tabla o realizar una inserción masiva de un porcentaje grande de las filas. Esto puede evitar los retrasos futuros en el procesamiento de la consulta, mientras las consultas esperan las actualizaciones automáticas de las estadísticas.

Otras operaciones, como regenerar, desfragmentar o reorganizar un índice, no cambian la distribución de los datos. Por consiguiente, no necesita actualizar las estadísticas después de realizar las operaciones ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG o ALTER INDEX REORGANIZE. El Optimizador de consultas actualiza las estadísticas cuando regenera un índice en una tabla o vista con ALTER INDEX REBUILD o DBCC DBREINDEX. Sin embargo, esta actualización de las estadísticas es un subproducto de la recreación del índice. El Optimizador de consultas no actualiza las estadísticas después de las operaciones DBCC INDEXDEFRAG o ALTER INDEX REORGANIZE.

Sugerencia

A partir de SQL Server 2016 (13.x) SP1 CU4, utilice la opción PERSIST_SAMPLE_PERCENT de CREATE STATISTICS (Transact-SQL) o UPDATE STATISTICS (Transact-SQL) para establecer y mantener un porcentaje de muestreo específico para las actualizaciones de estadísticas posteriores en las que no se especifica explícitamente un porcentaje de muestreo.

Administración automática de índice y estadísticas

Aproveche soluciones como la desfragmentación de índice adaptable para administrar automáticamente las actualizaciones de estadísticas y la desfragmentación de índices para una o varias bases de datos. Este procedimiento elige automáticamente si se debe volver a generar o reorganizar un índice según su nivel de fragmentación, entre otros parámetros y actualiza las estadísticas con un umbral lineal.

Consultas que usan eficazmente las estadísticas

Algunas implementaciones de consulta, como las variables locales y las expresiones complejas en el predicado de consulta, pueden conducir a planes de consulta que no son óptimos. Las siguientes instrucciones de diseño de consulta para el uso eficaz de las estadísticas pueden evitarlo. Para obtener más información sobre los predicados de consulta, consulteCondición de búsqueda (Transact-SQL).

Puede mejorar los planes de consulta aplicando instrucciones de diseño de consulta que utilicen las estadísticas con eficacia para mejorar las estimaciones de cardinalidad en las expresiones, variables y funciones utilizadas en los predicados de consulta. Cuando el Optimizador de consultas no conoce el valor de una expresión, variable o función, no conoce qué valor ha de buscar en el histograma y, por consiguiente, no puede recuperar del histograma la mejor estimación de cardinalidad. En cambio, el Optimizador de consultas basa la estimación de cardinalidad en el número medio de filas por valor distinto para todas las filas buscadas en el histograma. El resultado son estimaciones de cardinalidad poco óptimas, además de dañar el rendimiento de la consulta. Para más información sobre los histogramas, vea la sección Histograma en esta página o sys.dm_db_stats_histogram.

Las instrucciones siguientes describen cómo escribir las consultas para mejorar los planes de consulta mediante la mejora de las estimaciones de cardinalidad.

Mejorar de las estimaciones de cardinalidad en las expresiones

Para mejorar las estimaciones de cardinalidad en las expresiones, siga estas instrucciones:

  • Siempre que sea posible, simplifique las expresiones utilizando constantes. El Optimizador de consultas no evalúa todas las funciones y expresiones que contienen constantes antes de determinar las estimaciones de cardinalidad. Por ejemplo, simplifique la expresión ABS(-100) en 100.
  • Si la expresión utiliza varias variables, considere la creación de una columna calculada para la expresión y, a continuación, cree estadísticas o un índice en la columna calculada. Por ejemplo, el predicado de consulta WHERE PRICE + Tax > 100 podría tener una mejor estimación de cardinalidad si crea una columna calculada para la expresión Price + Tax.

Mejora de las estimaciones de cardinalidad en las variables y funciones

Para mejorar las estimaciones de cardinalidad en las variables y funciones, siga estas instrucciones:

  • Si el predicado de consulta utiliza una variable local, considere volver a escribir la consulta usando un parámetro en lugar de una variable local. No se conoce el valor de una variable local cuando el Optimizador de consultas crea el plan de ejecución de la consulta. Cuando una consulta utiliza un parámetro, el Optimizador de consultas utiliza la estimación de cardinalidad para el primer valor de parámetro real que se pasa al procedimiento almacenado.

  • Le recomendamos que use una tabla estándar o una tabla temporal para retener los resultados de las funciones con valores de tabla de múltiples instrucciones (mstvf). El Optimizador de consultas no crea estadísticas para las funciones con valores de tabla de múltiples instrucciones. Con este enfoque, el Optimizador de consultas puede crear estadísticas sobre las columnas de tabla y utilizarlas para crear un plan de consulta mejor.

  • Considere el uso de una tabla estándar o una tabla temporal como un reemplazo para las variables de tabla. El Optimizador de consultas no crea estadísticas para las variables de tabla. Con este enfoque, el Optimizador de consultas puede crear estadísticas sobre las columnas de tabla y utilizarlas para crear un plan de consulta mejor. Hay que determinar si se utilizar una tabla temporal o una variable de tabla; las variables de tabla utilizadas en los procedimientos almacenados causan menos recompilaciones del procedimiento almacenado que las tablas temporales. Dependiendo de la aplicación, el uso de una tabla temporal en lugar de una variable de tabla no mejora el rendimiento.

  • Si un procedimiento almacenado contiene una consulta que utiliza un parámetro pasado, evite cambiar el valor del parámetro dentro del procedimiento almacenado antes de utilizarlo en la consulta. Las estimaciones de cardinalidad para la consulta se basan en el valor de parámetro pasado y no en el valor actualizado. Para evitar cambiar el valor del parámetro, puede reescribir la consulta para utilizar los dos procedimientos almacenados.

    Por ejemplo, el procedimiento almacenado siguiente Sales.GetRecentSales cambia el valor del parámetro @date cuando @date es NULL.

    USE AdventureWorks2022;
    GO
    IF OBJECT_ID ( 'Sales.GetRecentSales', 'P') IS NOT NULL
        DROP PROCEDURE Sales.GetRecentSales;
    GO
    CREATE PROCEDURE Sales.GetRecentSales (@date datetime)
    AS BEGIN
        IF @date IS NULL
            SET @date = DATEADD(MONTH, -3, (SELECT MAX(ORDERDATE) FROM Sales.SalesOrderHeader))
        SELECT * FROM Sales.SalesOrderHeader h, Sales.SalesOrderDetail d
        WHERE h.SalesOrderID = d.SalesOrderID
        AND h.OrderDate > @date
    END
    GO
    

    Si la primera llamada al procedimiento almacenado Sales.GetRecentSales pasa un NULL para el parámetro @date, el Optimizador de consultas compilará el procedimiento almacenado con la estimación de cardinalidad para @date = NULL aunque no se llame al predicado de consulta con @date = NULL. Esta estimación de cardinalidad podría ser significativamente diferente del número de filas del resultado de la consulta real. Como resultado, el Optimizador de consultas podría elegir un plan de consulta poco óptimo. Para ayudar a evitar esto, puede rescribir el procedimiento almacenado en dos procedimientos del modo siguiente:

    USE AdventureWorks2022;
    GO
    IF OBJECT_ID ( 'Sales.GetNullRecentSales', 'P') IS NOT NULL
        DROP PROCEDURE Sales.GetNullRecentSales;
    GO
    CREATE PROCEDURE Sales.GetNullRecentSales (@date datetime)
    AS BEGIN
        IF @date is NULL
            SET @date = DATEADD(MONTH, -3, (SELECT MAX(ORDERDATE) FROM Sales.SalesOrderHeader))
        EXEC Sales.GetNonNullRecentSales @date;
    END
    GO
    IF OBJECT_ID ( 'Sales.GetNonNullRecentSales', 'P') IS NOT NULL
        DROP PROCEDURE Sales.GetNonNullRecentSales;
    GO
    CREATE PROCEDURE Sales.GetNonNullRecentSales (@date datetime)
    AS BEGIN
        SELECT * FROM Sales.SalesOrderHeader h, Sales.SalesOrderDetail d
        WHERE h.SalesOrderID = d.SalesOrderID
        AND h.OrderDate > @date
    END
    GO
    

Mejora de las estimaciones de cardinalidad con sugerencias de consulta

Para mejorar las estimaciones de cardinalidad para las variables locales, puede usar las sugerencias de consulta OPTIMIZE FOR <value> o OPTIMIZE FOR UNKNOWN con RECOMPILE. Para obtener más información, consulte Sugerencias de consulta (Transact-SQL).

En algunas aplicaciones, volver a compilar la consulta cada vez que la ejecuta podría tardar demasiado tiempo. La sugerencia de consulta OPTIMIZE FOR puede servir de ayuda incluso si no usa la opción RECOMPILE. Por ejemplo, podría agregar una opción OPTIMIZE FOR al procedimiento almacenado Sales.GetRecentSales para especificar una fecha concreta. En el ejemplo siguiente, se agrega la opción OPTIMIZE FOR al procedimiento Sales.GetRecentSales.

USE AdventureWorks2022;
GO
IF OBJECT_ID ( 'Sales.GetRecentSales', 'P') IS NOT NULL
    DROP PROCEDURE Sales.GetRecentSales;
GO
CREATE PROCEDURE Sales.GetRecentSales (@date datetime)
AS BEGIN
    IF @date is NULL
        SET @date = DATEADD(MONTH, -3, (SELECT MAX(ORDERDATE) FROM Sales.SalesOrderHeader))
    SELECT * FROM Sales.SalesOrderHeader h, Sales.SalesOrderDetail d
    WHERE h.SalesOrderID = d.SalesOrderID
    AND h.OrderDate > @date
    OPTION ( OPTIMIZE FOR ( @date = '2004-05-01 00:00:00.000'))
END;
GO

Mejora de las estimaciones de cardinalidad con guías de plan

En algunos casos, las directrices de diseño de consultas podrían no aplicarse, bien porque no pueda cambiar la consulta, bien porque la sugerencia de consulta RECOMPILE cause demasiadas recompilaciones. Puede utilizar las guías de plan para especificar otras sugerencias, como USE PLAN, para controlar el comportamiento de la consulta mientras investiga los cambios de la aplicación con el proveedor de la aplicación. Para obtener más información acerca de las guías de plan, vea Plan Guides.

En Azure SQL Database, considere Sugerencias del almacén de consultas para forzar los planes, en lugar de las guías de plan. Para obtener más información, vea Sugerencias del Almacén de consultas.

Consulte también

Pasos siguientes