Nous avons une grande base de données, environ 1 To, exécutant SQL Server 2014 sur un serveur puissant. Tout a bien fonctionné pendant quelques années. Il y a environ 2 semaines, nous avons effectué une maintenance complète, qui comprenait: installer toutes les mises à jour logicielles; reconstruisez tous les index et les fichiers DB compacts. Cependant, nous ne nous attendions pas à ce qu'à un certain stade, l'utilisation du processeur de la base de données augmente de plus de 100% à 150% lorsque la charge réelle était la même.
Après beaucoup de dépannage, nous l'avons réduit à une requête très simple, mais nous n'avons pas pu trouver de solution. La requête est extrêmement simple:
select top 1 EventID from EventLog with (nolock) order by EventID
Cela prend toujours environ 1,5 seconde! Cependant, une requête similaire avec "desc" prend toujours environ 0 ms:
select top 1 EventID from EventLog with (nolock) order by EventID desc
PTable compte environ 500 millions de lignes; EventID
est la colonne d'index cluster principal (ordonnée ASC
) avec le type de données bigint (colonne Identity). Il y a plusieurs threads insérant des données dans la table en haut (plus gros EventID), et il y a 1 thread qui supprime les données du bas (plus petits EventID).
Dans SMSS, nous avons vérifié que les deux requêtes utilisent toujours le même plan d'exécution:
Analyse d'index en cluster;
Les nombres de lignes estimés et réels sont tous deux 1;
Le nombre estimé et réel d'exécutions est de 1;
Le coût d'E / S estimé est de 8500 (semble élevé)
S'il est exécuté consécutivement, le coût de la requête est le même de 50% pour les deux.
J'ai mis à jour les statistiques d'index with fullscan
, le problème a persisté; J'ai reconstruit à nouveau l'index, et le problème semblait avoir disparu pendant une demi-journée, mais est revenu.
J'ai activé les statistiques d'E / S avec:
set statistics io on
puis a exécuté les deux requêtes consécutivement et a trouvé les informations suivantes:
(Pour la première requête, la lente)
Tableau «PTable». Nombre de balayages 1, lectures logiques 407670, lectures physiques 0, lectures anticipées 0, lectures logiques 0, lob lectures physiques 0, lob lectures anticipées 0.
(Pour la deuxième requête, la rapide)
Tableau «PTable». Nombre de balayages 1, lectures logiques 4, lectures physiques 0, lectures anticipées 0, lectures logiques 0, lob lectures physiques 0, lob lectures anticipées 0.
Notez l'énorme différence dans les lectures logiques. L'index est utilisé dans les deux cas.
La fragmentation de l'indice pourrait expliquer un peu, mais je pense que l'impact est très faible; et le problème ne s'est jamais produit auparavant. Une autre preuve est que si je lance une requête comme:
select * from EventLog with (nolock) where EventID=xxxx
Même si j'ai défini xxxx sur les plus petits EventID de la table, la requête est toujours rapide comme l'éclair.
Nous avons vérifié et il n'y a aucun problème de verrouillage / blocage.
Remarque: J'ai juste essayé de simplifier le problème ci-dessus. Le "PTable" est en fait "EventLog"; l' PID
est EventID
.
J'obtiens le même résultat de test sans l' NOLOCK
astuce.
Quelqu'un peut-il aider?
Plans d'exécution de requête plus détaillés en XML comme suit:
https://www.brentozar.com/pastetheplan/?id=SJ3eiVnob
https://www.brentozar.com/pastetheplan/?id=r1rOjVhoZ
Je ne pense pas qu'il soit important de fournir l'instruction create table. Il s'agit d'une ancienne base de données qui fonctionne parfaitement bien depuis longtemps jusqu'à la maintenance. Nous avons fait beaucoup de recherches nous-mêmes et l'avons réduit aux informations fournies dans ma question.
La table a été créée normalement avec la EventID
colonne comme clé primaire, qui est une identity
colonne de type bigint
. Pour l'instant, je suppose que le problème vient de la fragmentation de l'index. Juste après la reconstruction de l'index, le problème semblait avoir disparu pendant une demi-journée; mais pourquoi il est revenu si vite ...?