Je vais le dire dès le début que ma question / problème ressemble à ce précédent, mais comme je ne suis pas sûr si la cause ou l'information de départ est le même, j'ai décidé de poster ma question avec quelques détails.
Problème à résoudre:
- à une heure étrange (vers la fin du jour ouvrable), une instance de production commence à se comporter de façon irrégulière:
- CPU élevé pour l'instance (à partir d'une ligne de base d'environ 30%, il est passé à environ le double et continue de croître)
- augmentation du nombre de transactions / s (bien que la charge de l'application n'ait vu aucun changement)
- augmentation du nombre de sessions inactives
- des événements de blocage étranges entre des sessions qui n'ont jamais affiché ce comportement (même la lecture de sessions non validées provoquait un blocage)
- les premières attentes pour l'intervalle étaient le verrouillage de la page à la 1ère place, les verrous prenant la 2e place
Enquête initiale:
- en utilisant sp_whoIsActive, nous avons vu qu'une requête exécutée par notre outil de surveillance décide de s'exécuter extrêmement lentement et de récupérer beaucoup de CPU, ce qui n'était pas arrivé auparavant;
- son niveau d'isolement a été lu sans engagement;
- nous avons regardé le plan, nous avons vu des nombres farfelus: StatementEstRows = "3.86846e + 010" avec quelque 150 To de données estimées à renvoyer
- nous soupçonnions qu'une fonctionnalité de surveillance des requêtes de l'outil de surveillance en était la cause, nous avons donc désactivé la fonctionnalité (nous avons également ouvert un ticket avec notre fournisseur pour vérifier s'il est au courant d'un problème)
- depuis ce premier événement, cela s'est produit quelques fois de plus, à chaque fois que nous tuons la session, tout revient à la normale;
- nous réalisons que la requête est extrêmement similaire à l' une des requêtes utilisées par MS dans BOL pour la surveillance du magasin de requêtes - Requêtes qui ont récemment régressé en termes de performances (en comparant différents points dans le temps)
- nous exécutons la même requête manuellement et voyons le même comportement (CPU utilisé toujours croissant, attente de verrouillage croissante, verrous inattendus, etc.)
Requête coupable:
Select qt.query_sql_text,
q.query_id,
qt.query_text_id,
rs1.runtime_stats_id AS runtime_stats_id_1,
interval_1 = DateAdd(minute, -(DateDiff(minute, getdate(), getutcdate())), rsi1.start_time),
p1.plan_id AS plan_1,
rs1.avg_duration AS avg_duration_1,
rs2.avg_duration AS avg_duration_2,
p2.plan_id AS plan_2,
interval_2 = DateAdd(minute, -(DateDiff(minute, getdate(), getutcdate())), rsi2.start_time),
rs2.runtime_stats_id AS runtime_stats_id_2
From sys.query_store_query_text AS qt
Inner Join sys.query_store_query AS q
ON qt.query_text_id = q.query_text_id
Inner Join sys.query_store_plan AS p1
ON q.query_id = p1.query_id
Inner Join sys.query_store_runtime_stats AS rs1
ON p1.plan_id = rs1.plan_id
Inner Join sys.query_store_runtime_stats_interval AS rsi1
ON rsi1.runtime_stats_interval_id = rs1.runtime_stats_interval_id
Inner Join sys.query_store_plan AS p2
ON q.query_id = p2.query_id
Inner Join sys.query_store_runtime_stats AS rs2
ON p2.plan_id = rs2.plan_id
Inner Join sys.query_store_runtime_stats_interval AS rsi2
ON rsi2.runtime_stats_interval_id = rs2.runtime_stats_interval_id
Where rsi1.start_time > DATEADD(hour, -48, GETUTCDATE())
AND rsi2.start_time > rsi1.start_time
AND p1.plan_id <> p2.plan_id
AND rs2.avg_duration > rs1.avg_duration * 2
Order By q.query_id, rsi1.start_time, rsi2.start_time
Paramètres et informations:
- SQL Server 2016 SP1 CU4 Enterprise sur un cluster Windows Server 2012R2
- Query Store activé et configuré par défaut (aucun paramètre modifié)
- base de données importée à partir d'une instance SQL 2005 (et toujours au niveau de compatibilité 100)
Observation empirique:
- en raison de statistiques extrêmement loufoques, nous avons pris tous les objets * plan_persist ** utilisés dans le mauvais plan estimé (pas encore de plan réel, car la requête n'est jamais terminée) et vérifié les statistiques, certains des index utilisés dans le plan n'avaient pas de statistiques (DBCC SHOWSTATISTICS n'a rien retourné, sélectionnez dans sys.stats la fonction NULL stats_date () pour certains index
Solution rapide et sale:
- créer manuellement des statistiques manquantes sur les objets système liés au magasin de requêtes ou
- forcer la requête à s'exécuter en utilisant le nouveau CE (traceflag) - qui créera / mettra également à jour les statistiques nécessaires ou
- changer le niveau de compatibilité de la base de données à 130 (il utilisera donc par défaut le nouveau CE)
Donc, ma vraie question serait:
Pourquoi une requête sur le magasin de requêtes entraînerait-elle des problèmes de performances sur l'instance entière? Sommes-nous dans un territoire de bogues avec Query Store?
PS: je vais télécharger quelques fichiers (écrans d'impression, statistiques IO et plans) dans un court instant.
Fichiers ajoutés sur Dropbox .
Plan 1 - Plan initial loufoque estimé en production
Plan 2 - plan réel, ancien CE, dans un environnement de test (même comportement, mêmes statistiques loufoques)
Plan 3 - plan actuel, nouveau CE, dans un environnement de test