Risposte:
Puoi tenere presente quanto segue quando ti preoccupi dell'aggiornamento delle statistiche (copiato da Ricostruzione degli indici e aggiornamento delle statistiche (Benjamin Nevarez)
Per impostazione predefinita, l' UPDATE STATISTICS
istruzione utilizza solo un campione di record della tabella. Utilizzando UPDATE STATISTICS WITH FULLSCAN
verrà eseguita la scansione dell'intera tabella.
Per impostazione predefinita, l' UPDATE STATISTICS
istruzione aggiorna le statistiche dell'indice e della colonna. L'uso COLUMNS
dell'opzione aggiornerà solo le statistiche delle colonne. L'uso INDEX
dell'opzione aggiornerà solo le statistiche dell'indice.
La ricostruzione di un indice , ad esempio utilizzando ALTER INDEX … REBUILD
, aggiornerà anche le statistiche dell'indice con l'equivalente dell'utilizzo a WITH FULLSCAN
meno che la tabella non sia partizionata, nel qual caso le statistiche vengono campionate solo (si applica a SQL Server 2012 e versioni successive).
Le statistiche create manualmente utilizzando CREATE STATISTICS
non vengono aggiornate da alcuna ALTER INDEX ... REBUILD
operazione, incluso ALTER TABLE ... REBUILD
. ALTER TABLE ... REBUILD
aggiorna le statistiche per l'indice cluster, se ne è definito uno nella tabella da ricostruire.
La riorganizzazione di un indice , ad esempio l'utilizzo ALTER INDEX … REORGANIZE
non aggiorna alcuna statistica.
La risposta breve è che è necessario utilizzare UPDATE STATISTICS
per aggiornare le statistiche delle colonne e che una ricostruzione dell'indice aggiornerà solo le statistiche dell'indice. È possibile forzare un aggiornamento di tutte le statistiche su una tabella, comprese le statistiche indice e le statistiche create manualmente, con la UPDATE STATISTICS (tablename) WITH FULLSCAN;
sintassi.
Il seguente codice illustra le regole incapsulate sopra:
Innanzitutto, creeremo una tabella con un paio di colonne e un indice cluster:
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;
Questa query mostra la data dell'ultimo aggiornamento di ogni oggetto stats:
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';
I risultati mostrano che non sono ancora stati effettuati aggiornamenti, il che è corretto da quando abbiamo appena creato la tabella:
╔═══════════════╦═══════════╦═══════════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═══════════╣ ║ dbo.SomeTable ║ cx ║ NULL ║ ║ dbo.SomeTable ║ i ║ NULL ║ ║ dbo.SomeTable ║ pk ║ NULL ║ ║ dbo.SomeTable ║ d ║ NULL ║ ╚═══════════════╩═══════════╩═══════════╝
Ricostruiamo l'intera tabella e vediamo se aggiorna le statistiche:
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. Qualche tabella ║ cx ║ 2018-09-17 14: 09: 13.590 ║ ║ dbo.SomeTable ║ i ║ NULL ║ ║ dbo.SomeTable ║ pk ║ NULL ║ ║ dbo.SomeTable ║ d ║ NULL ║ ╚═══════════════╩═══════════╩═════════════════════ ════╝
I risultati mostrano che sono state aggiornate solo le statistiche dell'indice cluster .
Successivamente, eseguiamo un'operazione discreta UPDATE STATS
:
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';
Come puoi vedere, abbiamo appena aggiornato le statistiche nella d
colonna:
╔═══════════════╦═══════════╦═════════════════════ ════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═════════════════════ ════╣ ║ dbo. Qualche tabella ║ cx ║ 2018-09-17 14: 09: 13.590 ║ ║ dbo.SomeTable ║ i ║ NULL ║ ║ dbo.SomeTable ║ pk ║ NULL ║ ║ dbo. Qualche tabella ║ d ║ 2018-09-17 14: 09: 13.597 ║ ╚═══════════════╩═══════════╩═════════════════════ ════╝
Ora aggiorneremo le statistiche sull'intera tabella:
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. Qualche tabella ║ cx ║ 2018-09-17 14: 09: 13.600 ║ ║ dbo. Qualche tabella ║ i ║ 2018-09-17 14: 09: 13.600 ║ ║ dbo. Qualche tabella ║ pk ║ 2018-09-17 14: 09: 13.603 ║ ║ dbo. Qualche tabella ║ d ║ 2018-09-17 14: 09: 13.607 ║ ╚═══════════════╩═══════════╩═════════════════════ ════╝
Come puoi vedere, l'unico modo per essere certi che tutte le statistiche siano aggiornate è di aggiornarle manualmente o di aggiornare l'intera tabella UPDATE STATISTICS (table);
.
ALTER INDEX ... REBUILD
o una UPDATE STATISTICS
dichiarazione. Se la tabella stessa viene ricostruita, vengono aggiornate solo le statistiche dell'indice cluster. Cordiali saluti, una chiave primaria e un indice cluster non sono necessariamente supportati dallo stesso oggetto indice.
La pagina Microsoft Docs per le statistiche di SQL Server indica :
Operazioni come la ricostruzione, la deframmentazione o la riorganizzazione di un indice non cambiano la distribuzione dei dati. Pertanto, non è necessario aggiornare le statistiche dopo aver eseguito ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG o ALTER INDEX REORGANIZE . Query Optimizer aggiorna le statistiche quando si ricostruisce un indice su una tabella o si visualizza con ALTER INDEX REBUILD o DBCC DBREINDEX, tuttavia questo aggiornamento delle statistiche è un sottoprodotto della ricostruzione dell'indice. Query Optimizer non aggiorna le statistiche dopo le operazioni DBCC INDEXDEFRAG o ALTER INDEX REORGANIZE.
REINDEX
aggiorna le statistiche delle colonne come effetto collaterale della ricostruzione dell'indice: non è necessario aggiornare le statistiche. I dati nella tabella non cambiano. Sono gli stessi dati, solo a) spostato la sua posizione sul piatto rotante (quando una pagina viene riorganizzata), oppure b) seduto in una pagina diversa (nel caso di una ricostruzione). Quindi: una ri-index fa update (alcuni) statistiche: non c'è bisogno di farlo.