Respuestas:
Puede tener en cuenta lo siguiente al preocuparse por actualizar las estadísticas (copiado de Reconstruir índices frente a Actualizar estadísticas (Benjamin Nevarez)
Por defecto, la UPDATE STATISTICS
declaración usa solo una muestra de registros de la tabla. El uso UPDATE STATISTICS WITH FULLSCAN
escaneará toda la tabla.
Por defecto, la UPDATE STATISTICS
declaración actualiza las estadísticas de índice y columna. El uso de la COLUMNS
opción actualizará solo las estadísticas de columna. El uso de la INDEX
opción actualizará solo las estadísticas de índice.
La reconstrucción de un índice , por ejemplo, mediante el uso ALTER INDEX … REBUILD
también actualizará las estadísticas del índice con el equivalente de usar a WITH FULLSCAN
menos que la tabla esté particionada, en cuyo caso las estadísticas solo se muestrean (se aplica a SQL Server 2012 y versiones posteriores).
Las estadísticas que se crearon manualmente usando CREATE STATISTICS
no se actualizan por ninguna ALTER INDEX ... REBUILD
operación, incluida ALTER TABLE ... REBUILD
. ALTER TABLE ... REBUILD
actualiza las estadísticas para el índice agrupado, si se define uno en la tabla que se está reconstruyendo.
La reorganización de un índice , por ejemplo, el uso ALTER INDEX … REORGANIZE
no actualiza ninguna estadística.
La respuesta breve es que debe usar UPDATE STATISTICS
para actualizar las estadísticas de columna y que una reconstrucción de índice actualizará solo las estadísticas de índice. Puede forzar una actualización de todas las estadísticas en una tabla, incluidas las estadísticas de índice y las estadísticas creadas manualmente, con la UPDATE STATISTICS (tablename) WITH FULLSCAN;
sintaxis.
El siguiente código ilustra las reglas encapsuladas anteriormente:
Primero, crearemos una tabla con un par de columnas y un índice agrupado:
USE tempdb;
IF OBJECT_ID(N'dbo.SomeTable', N'U') IS NOT NULL
DROP TABLE dbo.SomeTable;
CREATE TABLE dbo.SomeTable
(
rn int NOT NULL IDENTITY(1,1)
CONSTRAINT pk
PRIMARY KEY NONCLUSTERED
, i int NOT NULL INDEX i
, d sysname NOT NULL
) ON [PRIMARY] WITH (DATA_COMPRESSION = NONE);
CREATE UNIQUE CLUSTERED INDEX cx ON dbo.SomeTable (i, d);
CREATE STATISTICS d ON dbo.SomeTable (d) WITH FULLSCAN;
INSERT INTO dbo.SomeTable (d, i)
SELECT c1.name, c1.id
FROM sys.syscolumns c1;
Esta consulta muestra la fecha en que cada objeto de estadísticas se actualizó por última vez:
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
Los resultados muestran que aún no se han realizado actualizaciones, lo cual es correcto desde que acabamos de crear la tabla:
╔═══════════════╦═══════════╦═══════════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═══════════╣ ║ dbo.SomeTable ║ cx ║ NULL ║ Bo dbo.SomeTable ║ i ║ NULL ║ ║ dbo.SomeTable ║ pk ║ NULL ║ ║ dbo.SomeTable ║ d ║ NULL ║ ╚═══════════════╩═══════════╩═══════════╝
Vamos a reconstruir toda la tabla y ver si eso actualiza las estadísticas:
ALTER TABLE dbo.SomeTable REBUILD;
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═════════════════════ ════╣ ║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.590 ║ Bo dbo.SomeTable ║ i ║ NULL ║ ║ dbo.SomeTable ║ pk ║ NULL ║ ║ dbo.SomeTable ║ d ║ NULL ║ ╚═══════════════╩═══════════╩═════════════════════ ════╝
Los resultados muestran que solo se actualizaron las estadísticas del índice agrupado .
A continuación, realizamos una UPDATE STATS
operación discreta :
UPDATE STATISTICS dbo.SomeTable(d) WITH FULLSCAN;
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
Como puede ver, acabamos de actualizar las estadísticas en la d
columna:
╔═══════════════╦═══════════╦═════════════════════ ════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═════════════════════ ════╣ ║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.590 ║ Bo dbo.SomeTable ║ i ║ NULL ║ ║ dbo.SomeTable ║ pk ║ NULL ║ ║ dbo.SomeTable ║ d ║ 2018-09-17 14: 09: 13.597 ║ ╚═══════════════╩═══════════╩═════════════════════ ════╝
Ahora, actualizaremos las estadísticas de toda la tabla:
UPDATE STATISTICS dbo.SomeTable WITH FULLSCAN;
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═════════════════════ ════╣ ║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.600 ║ Bo dbo.SomeTable ║ i ║ 2018-09-17 14: 09: 13.600 ║ ║ dbo.SomeTable ║ pk ║ 2018-09-17 14: 09: 13.603 ║ ║ dbo.SomeTable ║ d ║ 2018-09-17 14: 09: 13.607 ║ ╚═══════════════╩═══════════╩═════════════════════ ════╝
Como puede ver, la única forma de asegurarse de que todas las estadísticas se actualicen es actualizar cada una manualmente o actualizar toda la tabla con UPDATE STATISTICS (table);
.
ALTER INDEX ... REBUILD
o una UPDATE STATISTICS
declaración. Si se reconstruye la tabla, solo se actualizan las estadísticas de índice agrupadas. Para su información, una clave principal y un índice agrupado no son necesariamente compatibles con el mismo objeto de índice.
La página de documentos de Microsoft para las estadísticas de SQL Server dice :
Operaciones como la reconstrucción, la desfragmentación o la reorganización de un índice no cambian la distribución de datos. Por lo tanto, no necesita actualizar las estadísticas después de realizar operaciones ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG o ALTER INDEX REORGANIZE . El Optimizador de consultas actualiza las estadísticas cuando reconstruye un índice en una tabla o vista con ALTER INDEX REBUILD o DBCC DBREINDEX, sin embargo, esta actualización de estadísticas es un subproducto de volver a crear el índice. Query Optimizer no actualiza las estadísticas después de las operaciones DBCC INDEXDEFRAG o ALTER INDEX REORGANIZE.
REINDEX
sí actualiza las estadísticas de columna como un efecto secundario de la reconstrucción del índice; no es necesario actualizar las estadísticas. Los datos en la tabla no cambian. Son los mismos datos, solo a) movió su ubicación en la bandeja giratoria (cuando se reorganiza una página), o b) se sentó en una página diferente (en el caso de una reconstrucción). Por lo tanto: una re-índice hace (algunos) las estadísticas de actualización: no hay necesidad de hacerlo.