Nous avons des bases de données avec des tables larges sur COLUMNSTORE
compression (21 ou 30 colonnes) et 2500 partitions (par date). Il existe environ 4000 objets statistiques dans cette base de données, dont la plupart sont des statistiques de colonne incrémentielles sur les tables partitionnées.
Lors de la course sys.dm_db_stats_properties
Sur ces bases de données, la performance de cette fonction de table est extrêmement médiocre. Nous examinons environ 1 seconde par ligne - c'est-à-dire par "gérer" de la fonction de cette table.
Voici un exemple du plan de requête généré par une simple requête avec le CROSS APPLY
Syntax utilisé pour exécuter cette fonction de table contre 1605 combinaisons de table-table-table.
Il n'y a rien de très utile ici - la performance est clairement pauvre du DMV.
Ma théorie actuelle est qu'en raison de la nature des objets statistiques de la base de données, la requête contre la table interne OpenRowset est mal optimisée (éventuellement le TOP 1
, et c'est ce qui cause le ralentissement.
CREATE FUNCTION sys.dm_db_stats_properties (@object_id int, @stats_id int)
RETURNS TABLE
AS
RETURN SELECT TOP 1 -- The first row in the TVF will be the root; avoid scanning entire TVF to find any additional rows.
object_id, -- Columns now explicit since underlying tvf has additional columns we don't want to expose for backwards compat
stats_id,
last_updated,
rows,
rows_sampled,
steps,
unfiltered_rows,
modification_counter,
persisted_sample_percent
FROM OPENROWSET(TABLE DM_DB_STATS_PROPERTIES, @object_id, @stats_id)
Cependant, étant donné que sys.dm_db_stats_properties
est un DMV et donc immuable, nous ne pouvons pas changer la façon dont il interroge les tables internes ou quoi que ce soit comme ça, autant que je sache.
L'objectif ici est d'obtenir les valeurs des colonnes rows, rows_sampled, unfiltered_rows, modification_counter, last_updated
comme obtenu de sys.dm_db_stats_properties
D'une manière qui ne prend pas 3 heures par base de données! Peu importe si nous utilisons un DMV différent, tant que la source des informations n'est pas moins précise.
Nous avons essayé de réorganiser toutes les tables système à voir si cela a un effet avec des déclarations telles que ALTER INDEX ALL ON [Database].sys.[table to reorganize] REORGANIZE
. Cependant, aucune augmentation de la performance n'a été observée.
Nous exécutons la version suivante de SQL Server: Microsoft SQL Server 2017 (RTM-CU18) (KB4527377) - 14.0.3257.3 (X64) sur Windows Server 2016.Le niveau de compatibilité est 140
Vous pouvez tout obtenir sauf modification_counter
de DBCC SHOW_STATISTICS
DBCC SHOW_STATISTICS ( table_or_indexed_view_name , target )
WITH STAT_HEADER;
Vous auriez besoin de capturer sa sortie dans une table temporaire en utilisant quelque chose comme:
CREATE TABLE #StatHeader
(
[Name] sysname NULL,
Updated datetime NULL,
[Rows] bigint NULL,
[Rows Sampled] bigint NULL,
Steps integer NULL,
Density float NULL,
[Average key length] integer NULL,
[String Index] varchar(3) NULL,
[Filter Expression] nvarchar(max) NULL,
[Unfiltered Rows] bigint NULL,
[Persisted Sample Percent] integer NULL
);
INSERT #StatHeader
EXECUTE('DBCC SHOW_STATISTICS (table, stat) WITH STAT_HEADER;');
Un compteur de modification de substitution est fourni par rowmodctr
sur sys.sysindexes
.
C'est une solution de contournement et ce que nous aurions fait avant que le nouveau DMV ait été fourni. Ce n'est pas idéal, et vous devez signaler les performances inattendues que vous voyez à Microsoft.