sql >> Base de Datos >  >> RDS >> Sqlserver

Estadísticas incrementales de SQL Server 2014

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 1
La 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 .