Nous avons un processus qui génère un rapport d'inventaire. Côté client, le processus fractionne un nombre configurable de threads de travail pour créer un bloc de données pour le rapport qui correspond à un magasin sur plusieurs (potentiellement des milliers, généralement des dizaines). Chaque thread de travail appelle un service Web qui exécute une procédure stockée.
Le processus de base de données pour le traitement de chaque bloc rassemble un tas de données dans une table #Temporary. À la fin de chaque bloc de traitement, les données sont écrites dans une table permanente dans tempdb. Enfin, à la fin du processus, un thread côté client demande toutes les données de la table tempdb permanente.
Plus il y a d'utilisateurs qui exécutent ce rapport, plus il ralentit. J'ai analysé l'activité dans la base de données. À un moment donné, j'ai vu 35 demandes distinctes toutes bloquées à un moment donné du processus. Tous ces SPID avaient de l'ordre de 50 ms d'attente de type LATCH_EX
sur ressource METADATA_SEQUENCE_GENERATOR (00000010E13CA1A8)
. Un SPID a cette ressource, et tous les autres bloquent. Je n'ai rien trouvé sur cette ressource d'attente lors d'une recherche sur le Web.
La table dans tempdb que nous utilisons a une IDENTITY(1,1)
colonne. Ces SPID attendent-ils la colonne IDENTITY? Quelles méthodes pourrions-nous utiliser pour réduire ou éliminer le blocage?
Le serveur fait partie d'un cluster. Le serveur exécute SQL Server 2012 Standard Edition SP1 64 bits sur Windows 2008 R2 Enterprise 64 bits. Le serveur a 64 Go de RAM et 48 processeurs, mais la base de données ne peut en utiliser que 16 car il s'agit de l'édition standard.
(Notez que je ne suis pas ravi de la conception d'utiliser une table permanente dans tempdb pour conserver toutes ces données. Changer cela serait un défi technique et politique intéressant, mais je suis ouvert aux suggestions.)
MISE À JOUR 23/04/2013
Nous avons ouvert un dossier d'assistance avec Microsoft. Je garderai cette question à jour à mesure que nous en apprendrons davantage.
MISE À JOUR 5/10/2013
L'ingénieur de support SQL Server a convenu que les attentes étaient causées par la colonne IDENTITY. La suppression de l'IDENTITÉ a éliminé les attentes. Nous n'avons pas pu dupliquer le problème sur SQL 2008 R2; cela s'est produit uniquement sur SQL 2012.
la source
Réponses:
En supposant que vous pouvez isoler le problème de la génération de valeurs d'identité (essayez de supprimer cette colonne en tant que test), je recommanderais ceci:
IDENTITY
propriété de la colonne du tableau final.Donc, si vous avez des identifiants de magasin 3 et 4, vous vous retrouveriez avec des valeurs finales d'ID comme ceci:
Ou quelque chose de similaire à ça. Vous avez eu l'idée.
Cela éliminera le besoin de sérialiser la
IDENTITY
génération tout en préservant l'unicité du résultat final.Alternativement, selon la façon dont le processus fonctionne, insérez les valeurs finales d'ID calculées dans les tables #Temporary. Ensuite, vous pouvez créer une vue qui
UNION ALL
les regroupe, éliminant ainsi la nécessité de copier les données.la source
IDENTITY
colonne. Nous l'avons retiré de l'index cluster déjà large et supprimé complètement la colonne. Ce n'était pas nécessaire. Par la suite, ces attentes LATCH_EX ont disparu. Nous n'avons pas pu dupliquer les attentes sur SQL 2008 R2. Le problème ne s'est produit que sur SQL Server 2012.IDENTITY
valeurs a été réécrit pour utiliser le nouveau truc de génération de séquence qui était nouveau en 2012. Sur <2012, vous pouvez voir un type de verrou différent, bien que s'il n'y avait pas de problème de performance, il semble qu'il y en ait eu une régression dans le code. Dans tous les cas, la suppression de laIDENTITY
colonne est la chose la plus sûre.(Mise à jour février 2019)
Ceci est un vieux post, qui a dit que j'ai finalement réussi à convaincre Microsoft que le fait même que cela se produise est en effet un défaut.
Mise à jour: MS a confirmé le défaut et lui a attribué un bogue n ° 12628722.
J'avais vu ce message en novembre 2018 lorsque nous avons commencé à souffrir à peu près la même chose après la mise à niveau de Sql Server 2005 vers Sql Server 2017. Une table de 3,3 millions de lignes qui prenait 10 secondes pour l'insertion en vrac a soudainement commencé à prendre 10 minutes sur des tables avec des
Identity
colonnes.Il s'avère qu'il y a deux problèmes derrière cela:
Cela m'a pris 4 semaines mais juste après les vacances, j'ai reçu un cadeau tardif du Père Noël - confirmation que le problème était effectivement un défaut.
Il existe quelques solutions possibles que nous avons trouvées jusqu'à ce que cela soit résolu:
Option (MaxDop 1)
dans la requête pour reconvertir l'insertion en bloc en un plan sérialisé.Select Cast(MyIdentityColumn As Integer) As MyIdentityColumn
)SELECT...INTO
Mise à jour: Le correctif que MS implémentera consistera à renvoyer ces types d'insertions à l'aide d'un
Serialized
plan. Ceci est prévu pour Sql Server 2017 CU14 (pas de nouvelles sur les autres versions de Sql Server - désolé!). Une fois implémenté, Trace Flag 9492 devra être activé, soit au niveau du serveur, soit viaDBCC TraceOn
.la source