Ré-indexe-t-il les statistiques de mise à jour?

43

J'ai suivi le cours MS10775A la semaine dernière et une des questions à laquelle le formateur n'a pas pu répondre de manière fiable est la suivante:

Est-ce qu'une réindexation met à jour les statistiques?

Nous avons trouvé des discussions en ligne affirmant à la fois que oui et non.

Thor Erik
la source
Il est utile de noter que la REINDEXmise à jour des statistiques de colonne est un effet secondaire de la reconstruction de l'index - vous n'avez pas besoin de mettre à jour les statistiques. Les données dans la table ne changent pas. Ce sont les mêmes données, il a seulement déplacé son emplacement sur le plateau en rotation (lorsqu'une page est réorganisée), ou b) assis sur une page différente (dans le cas d'une reconstruction). Donc: une réindexation fait des statistiques de mise à jour (certains): il n'y a pas besoin de le faire.
Ian Boyd

Réponses:

51

Vous pouvez garder à l’esprit les points suivants lorsque vous vous souciez de la mise à jour des statistiques (copiées à partir de Reconstruire des index et mettre à jour des statistiques (Benjamin Nevarez)

  1. Par défaut, l' UPDATE STATISTICSinstruction utilise uniquement un échantillon d'enregistrements de la table. Utiliser UPDATE STATISTICS WITH FULLSCANva scanner toute la table.

  2. Par défaut, l' UPDATE STATISTICSinstruction met à jour les statistiques d'index et de colonne. Utiliser cette COLUMNSoption ne mettra à jour que les statistiques de colonne. Utiliser cette INDEXoption ne mettra à jour que les statistiques d'index.

  3. La reconstruction d'un index , par exemple en utilisant, ALTER INDEX … REBUILDmettra également à jour les statistiques d'index avec l'équivalent de l'utilisation WITH FULLSCAN sauf si la table est partitionnée, auquel cas les statistiques sont uniquement échantillonnées (s'applique à SQL Server 2012 et versions ultérieures).

  4. Les statistiques créées manuellement à l'aide de CREATE STATISTICSne sont mises à jour par aucune ALTER INDEX ... REBUILDopération, y compris ALTER TABLE ... REBUILD. ALTER TABLE ... REBUILDmet à jour les statistiques pour l'index clusterisé, s'il en existe un défini sur la table en cours de reconstruction.

  5. Réorganiser un index , par exemple, utiliser ALTER INDEX … REORGANIZEne met à jour aucune statistique.

La réponse courte est que vous devez utiliser UPDATE STATISTICSpour mettre à jour les statistiques de colonne et qu'une reconstruction d'index mettra à jour uniquement les statistiques d'index. Vous pouvez forcer la mise à jour de toutes les statistiques d'une table, y compris index-stats et statistiques créées manuellement, avec la UPDATE STATISTICS (tablename) WITH FULLSCAN;syntaxe.

Le code suivant illustre les règles encapsulées ci-dessus:

Tout d'abord, nous allons créer une table avec quelques colonnes et un index clusterisé:

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;

Cette requête indique la date de la dernière mise à jour de chaque objet de statistiques:

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';

Les résultats montrent qu'aucune mise à jour n'a encore eu lieu, ce qui est correct puisque nous venons de créer la table:

╔═══════════════╦═══════════╦═══════════╗
║ ObjectName ║ StatsName ║ StatsDate
╠═══════════════╬═══════════╬═══════════╣
║ dbo.SomeTable cx NULL
║ dbo.SomeTable i NULL
║ dbo.SomeTable pk ║ NULL
║ dbo.SomeTable d ║ NULL
╚═══════════════╩═══════════╩═══════════╝

Reconstruisons la table entière et voyons si cela met à jour les statistiques:

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
║ dbo.SomeTable i NULL
║ dbo.SomeTable pk ║ NULL
║ dbo.SomeTable d ║ NULL
╚═══════════════╩═══════════╩═════════════════════ ════╝

Les résultats montrent que seules les statistiques de l' index clusterisé ont été mises à jour.

Ensuite, nous effectuons une UPDATE STATSopération discrète :

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';

Comme vous pouvez le constater, nous venons de mettre à jour les statistiques de la dcolonne:

╔═══════════════╦═══════════╦═════════════════════ ════╗
║ ObjectName ║ StatsName ║ StatsDate
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable cx 2018-09-17 14: 09: 13.590
║ dbo.SomeTable i NULL
║ dbo.SomeTable pk ║ NULL
Dbo.SomeTable d ║ 2018-09-17 14: 09: 13.597
╚═══════════════╩═══════════╩═════════════════════ ════╝

Maintenant, nous allons mettre à jour les statistiques sur toute la table:

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
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
╚═══════════════╩═══════════╩═════════════════════ ════╝

Comme vous pouvez le constater, le seul moyen de vérifier que toutes les statistiques ont été mises à jour est de les mettre à jour manuellement ou de mettre à jour le tableau entier UPDATE STATISTICS (table);.

MicSim
la source
@JeremyWeir - comme vous pouvez le constater à partir de l'exemple de code que je viens d'ajouter à la question ci-dessus, les seules statistiques mises à jour sont celles explicitement mises à jour via ALTER INDEX ... REBUILDune UPDATE STATISTICSinstruction ou une déclaration. Si la table elle-même est reconstruite, seules les statistiques d'index en cluster sont mises à jour. Pour votre information, une clé primaire et un index clusterisé ne sont pas nécessairement pris en charge par le même objet d'index.
Max Vernon
5

La page Microsoft Documents pour les statistiques SQL Server indique :

Les opérations telles que la reconstruction, la défragmentation ou la réorganisation d'un index ne modifient pas la distribution des données. Par conséquent, il n'est pas nécessaire de mettre à jour les statistiques après avoir effectué les opérations ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG ou ALTER INDEX REORGANIZE . Query Optimizer met à jour les statistiques lorsque vous reconstruisez un index sur une table ou une vue avec ALTER INDEX REBUILD ou DBCC DBREINDEX. Toutefois, cette mise à jour de statistiques est un sous-produit de la recréation de l'index. Query Optimizer ne met pas à jour les statistiques après les opérations DBCC INDEXDEFRAG ou ALTER INDEX REORGANIZE.

bside
la source