web-dev-qa-db-fra.com

SQL Server - Colonne Varbinary - Mise à jour de statistiques extrêmement lentes

J'ai une table dans ma base de données que nous utilisons comme un filestore, le fichier lui-même est stocké dans une colonne varbinary, qui semblait tous fonctionner bien jusqu'à récemment, nous avons remarqué que l'une de nos instances de ce tableau avait essentiellement " coincé "sur une déclaration d'insertion.

Vérification sys.dm_os_waiting_tasks a montré que l'instruction insertion avait déclenché une mise à jour des statistiques et que cette mise à jour de statistiques prenait une très longtemps. (17 minutes).

Voici la déclaration que nous avons trouvée en cours d'exécution:

SELECT StatMan([SC0], [LC0]) FROM 
   (SELECT TOP 100 PERCENT CONVERT([varbinary](200), 
        SUBSTRING ([Data], 1, 100)++substring([Data], 
        case when LEN([Data])<=200 then 101 else 
        LEN([Data])-99 end, 100)) AS [SC0], 
        datalength([Data]) AS [LC0] 
    FROM [FileSystem].[FileData] WITH 
    (READUNCOMMITTED) ORDER BY [SC0] ) AS _MS_UPDSTATS_TBL

Il y a environ 2000 lignes dans cette table, voici à quoi cela ressemble:

CREATE TABLE [FileSystem].[FileData]
(
[Id] [uniqueidentifier] NOT NULL CONSTRAINT [DF__FileData__Id__09DE7BCC] DEFAULT     (newsequentialid()),
[Data] [varbinary] (max) NULL,
[FileHash] [nvarchar] (4000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[FileSize] [bigint] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [FileSystem].[FileData] ADD CONSTRAINT [PK_FileData] PRIMARY KEY     CLUSTERED  ([Id]) WITH (STATISTICS_NORECOMPUTE=ON) ON [PRIMARY]
GO

Nous sommes conscients que cette table est plutôt bizarre et nous sommes prudents de ne pas adresser à chaque adresse avec un indice en regroupement.

Pour le moment, nous avons simplement désactivé la génération automatique de statistiques pour cette table, mais je me demande si c'est vraiment la meilleure pratique. La performance finira-t-elle éventuellement à un problème sans statistiques à jour (gardez-vous à l'esprit, ce tableau n'est que tous les adressés par son index en cluster)?

Mettre à jour:
[.____] D'accord, je suis à peu près sûr que nous avons élaboré ce qui faisait générer la statistique:

GO CREATE PROCEDURE [FileSystem].[FileData_AppendNewData_Easy] 
    (@fileDataId  uniqueidentifier ) 
WITH EXECUTE AS CALLER AS 
BEGIN 
   declare @testValue varbinary(max); 

   set @testValue = 0xabcedf012439; 

   Update FileSystem.FileData 
   set Data.Write(@testValue, null, null) 
   where Id = @fileDataId ;
END

Ceci est une version simplifiée de la procédure qui causait la question, semble-t-il Data.Write provoque une sorte de prédicat implicite sur la colonne de données? Eh bien, cela résout que le mystère, même si je ne suis toujours pas sûr de ce que l'impact désactivant les statistiques de cette table pourrait avoir, quelqu'un peut-il commenter cela?

5
Chris Mawman

Cela peut être adressé de deux manières supplémentaires:

  1. Activez les statistiques de mise à jour automatique asynchrones et le niveau de la base de données (pas de ma préférence). Si votre production est bloquée car, en raison de ce problème, il s'agit de la solution rapide car elle est instantanée, mais elle affecte globalement la base de données et peut produire des plans de requête sous-par rapport à la production du plan avant la mise à jour des statistiques.

    ALTER DATABASE [DatabaseName] SET AUTO_UPDATE_STATISTICS_ASYNC ON WITH NO_WAIT
    
  2. Supprimer la statistique automatique générer et le remplacer par un en créé manuellement sans recalculer. L'inconvénient est que, s'il s'agit d'une approche chirurgicale, il faut du temps pour créer la statistique et provoquera le blocage.

    DROP STATISTICS [dbo].[TableName].[_WA_Sys_00000004_7D78A4E7]
    GO
    CREATE STATISTICS [_Manual_Stat_Name] ON [dbo].[TableName]([Column]) WITH NORECOMPUTE;
    GO
    

Lorsque nous avons été forcés de faire face à un problème similaire, nous sommes allés avec l'option 1 d'abord et une autre option 2. Lors d'une "zone verte", nous avons rétabli le paramètre large de la base de données, puis a remplacé la statistique de la colonne avec le norecompute créé manuellement.

3
artofsql

Pour le moment, nous avons simplement désactivé la génération de statistiques automatique pour ce tableau, mais je me demande si c'est vraiment la meilleure pratique.

Selon le commentaire Microsoft sur cet élément Connect , oui c'est:

Merci pour les commentaires. Nous examinerons cela pour une version future. Veuillez envisager d'utiliser la mise à jour manuelle des statistiques sur cette colonne pour maintenant et désactivez les mises à jour automatiques. Contactez Services de support client Microsoft Si vous ne pouvez pas proposer une solution de contournement et c'est un problème critique pour vous.

Meilleures salutations,
[.____] eric hanson
Gestionnaire de programme
[.____] Traitement de requête SQL Server

Dans SQL Server 2012, le comportement a été modifié afin que UPDATE Table SET x.WRITE ne déclenche plus la création de statistiques. D'autres types de requêtes peuvent encore entraîner des statistiques créées, de sorte que la désactivation des statistiques automatiques peut encore être la bonne chose à faire.

Mon moyen préféré de créer très rapidement des statistiques vierges qui ne seront pas automatiquement mises à jour est la suivante:

CREATE STATISTICS stats
ON dbo.Test (target_column)
WITH
    SAMPLE 0 ROWS, 
    NORECOMPUTE;
2
Paul White 9

La désactivation de la mise à jour automatique des statistiques de ce tableau dans cette situation devrait être une bonne amende, car vous ne répondez que chaque enregistrement par son indice en cluster unique. Étant donné que la sélectivité de l'index est parfaite et qu'elle ne change jamais, l'optimiseur ne doit jamais avoir besoin de regarder d'autres plans de requête en fonction des statistiques modifiées.

1
Dave Markle