Benjamin Nevarez es un consultor independiente con sede en Los Ángeles, California, que se especializa en el ajuste y la optimización de consultas de SQL Server. Es autor de "SQL Server 2014 Query Tuning &Optimization" y "Inside the SQL Server Query Optimizer" y coautor de "SQL Server 2012 Internals". Con más de 20 años de experiencia en bases de datos relacionales, Benjamin también ha sido ponente en muchas conferencias de SQL Server, incluidas PASS Summit, SQL Server Connections y SQLBits. El blog de Benjamin se puede encontrar en http://www.benjaminnevarez.com y también se le puede contactar por correo electrónico en admin en benjaminnevarez punto com y en twitter en @BenjaminNevarez.
Un problema importante con la actualización de estadísticas en tablas grandes en SQL Server es que siempre se debe escanear la tabla completa, por ejemplo, cuando se usa WITH FULLSCAN
opción, incluso si solo han cambiado los datos recientes. Esto también es cierto cuando se usa el particionamiento:incluso si solo la partición más nueva hubiera cambiado desde la última vez que se actualizaron las estadísticas, la actualización de las estadísticas nuevamente requería escanear toda la tabla, incluidas todas las particiones que no cambiaron. Las estadísticas incrementales, una nueva función de SQL Server 2014, pueden ayudar con este problema.
Con las estadísticas incrementales, puede actualizar solo la partición o particiones que necesita y la información de estas particiones se fusionará con la información existente para crear el objeto de estadísticas final. Otra ventaja de las estadísticas incrementales es que el porcentaje de cambios de datos necesarios para activar una actualización automática de estadísticas ahora funciona a nivel de partición, lo que básicamente significa que ahora solo se requiere el 20 % de las filas modificadas (cambios en la columna de estadísticas principal) por partición. Desafortunadamente, el histograma todavía está limitado a 200 pasos para todo el objeto de estadísticas en esta versión de SQL Server.
Veamos un ejemplo de cómo puede actualizar las estadísticas a nivel de partición para explorar su comportamiento al menos a partir de SQL Server 2014 CTP2. Primero necesitamos crear una tabla particionada usando la base de datos AdventureWorks2012:
CREATE PARTITION FUNCTION TransactionRangePF1 (DATETIME) AS RANGE RIGHT FOR VALUES ( '20071001', '20071101', '20071201', '20080101', '20080201', '20080301', '20080401', '20080501', '20080601', '20080701', '20080801' ); GO CREATE PARTITION SCHEME TransactionsPS1 AS PARTITION TransactionRangePF1 TO ( [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY] ); GO CREATE TABLE dbo.TransactionHistory ( TransactionID INT NOT NULL, -- not bothering with IDENTITY here ProductID INT NOT NULL, ReferenceOrderID INT NOT NULL, ReferenceOrderLineID INT NOT NULL DEFAULT (0), TransactionDate DATETIME NOT NULL DEFAULT (GETDATE()), TransactionType NCHAR(1) NOT NULL, Quantity INT NOT NULL, ActualCost MONEY NOT NULL, ModifiedDate DATETIME NOT NULL DEFAULT (GETDATE()), CONSTRAINT CK_TransactionType CHECK (UPPER(TransactionType) IN (N'W', N'S', N'P')) ) ON TransactionsPS1 (TransactionDate); GO
Nota:para obtener detalles sobre la partición y CREATE PARTITION FUNCTION / SCHEME
declaraciones, consulte Tablas e índices particionados en Books Online.
Actualmente tenemos datos para llenar 12 particiones. Comencemos poblando primero solo 11.
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate < '2008-08-01';
Si es necesario, puede usar la siguiente instrucción para inspeccionar el contenido de las particiones:
SELECT * FROM sys.partitions WHERE object_id = OBJECT_ID('dbo.TransactionHistory');
Vamos a crear un objeto de estadísticas incrementales usando CREATE STATISTICS
declaración con el nuevo INCREMENTAL
cláusula establecida en ON
(OFF
es el predeterminado):
CREATE STATISTICS incrstats ON dbo.TransactionHistory(TransactionDate) WITH FULLSCAN, INCREMENTAL = ON;
También puede crear estadísticas incrementales mientras crea un índice usando el nuevo STATISTICS_INCREMENTAL
cláusula del CREATE INDEX
declaración.
Puede inspeccionar el objeto de estadísticas creado usando DBCC
:
DBCC SHOW_STATISTICS('dbo.TransactionHistory', incrstats);
Entre otras cosas, notará que el histograma tiene 200 pasos (aquí solo se muestran los últimos 3):
RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | |
198 | 2008-07-25 00:00:00.000 | 187 | 100 | 2 |
199 | 2008-07-27 00:00:00.000 | 103 | 101 | 1 |
200 | 2008-07-31 00:00:00.000 | 281 | 131 | 3 |
Resultados DBCC iniciales
Así que ya tenemos el máximo de pasos en un objeto de estadísticas. ¿Qué sucedería si agrega datos a una nueva partición? Agreguemos datos a la partición 12:
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate >= '2008-08-01';
Ahora, actualizamos el objeto de estadísticas usando la siguiente declaración:
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH RESAMPLE ON PARTITIONS(12);
Tenga en cuenta la nueva sintaxis que especifica la partición, donde puede especificar varias particiones, separadas por comas. Las UPDATE STATISTICS
La declaración lee las particiones especificadas y luego combina sus resultados con el objeto de estadística existente para construir las estadísticas globales. Tenga en cuenta el RESAMPLE
cláusula; esto es necesario ya que las estadísticas de partición deben tener las mismas frecuencias de muestreo para fusionarse para crear las estadísticas globales. Aunque solo se analizó la partición especificada, puede ver que SQL Server ha reorganizado el histograma. Los últimos tres pasos ahora muestran datos para la partición agregada. También puede comparar el histograma original con el nuevo para otras diferencias menores:
RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | |
197 | 2008-07-31 00:00:00.000 | 150 | 131 | 2 |
198 | 2008-08-12 00:00:00.000 | 300 | 36 | 9 |
199 | 2008-08-22 00:00:00.000 | 229 | 43 | 7 |
200 | 2008-09-03 00:00:00.000 | 363 | 37 | 11 |
Resultados de DBCC después de la actualización incremental
Si por alguna razón desea deshabilitar las estadísticas incrementales, puede usar la siguiente declaración para volver al comportamiento original (u opcionalmente, simplemente suelte el objeto de estadísticas y cree uno nuevo).
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH FULLSCAN, INCREMENTAL = OFF;
Después de deshabilitar las estadísticas incrementales, intentar actualizar una partición como se muestra anteriormente devolverá el siguiente mensaje de error:
Mensaje 9111, nivel 16, estado 1La sintaxis de ACTUALIZAR ESTADÍSTICAS EN PARTICIONES no se admite para estadísticas no incrementales.
Finalmente, también puede habilitar estadísticas incrementales para sus estadísticas automáticas a nivel de base de datos, si es necesario. Esto requiere INCREMENTAL = ON
cláusula en ALTER DATABASE
declaración y obviamente también requiere AUTO_CREATE_STATISTICS
establecer en ON
.