Partager via


Superviser les performances avec le magasin des requêtes

S’APPLIQUE À : Azure Database pour PostgreSQL : serveur flexible

La fonctionnalité du magasin des requêtes du serveur flexible Azure Database pour PostgreSQL permet de suivre le niveau de performances des requêtes au fil du temps. Le magasin des requêtes simplifie la résolution des problèmes de performances en vous aidant à identifier rapidement les requêtes dont l’exécution est la plus longue et qui consomment le plus de ressources. Le magasin des requêtes capture automatiquement un historique des requêtes et des statistiques d’exécution, et les conserve pour que vous les passiez en revue. Il découpe les données par heure de façon à ce que vous puissiez voir des modèles d’utilisation temporelle. Les données de l’ensemble des utilisateurs, bases de données et requêtes sont stockées dans une base de données nommée azure_sys dans l’instance du serveur flexible Azure Database pour PostgreSQL.

Activer le magasin des requêtes

Le magasin des requêtes est utilisable sans frais supplémentaires. Il s’agit d’une fonctionnalité avec consentement, elle n’est pas activée par défaut sur un serveur. Le Magasin des requêtes peut être activé ou désactivé de façon globale pour toutes les bases de données se trouvant sur un serveur donné, et ne peut pas être activé ou désactivé par base de données.

Important

N’activez pas le magasin des requêtes sur le niveau tarifaire Burstable, car cela aurait un impact sur les performances.

Activer le magasin des requêtes sur le Portail Azure

  1. Connectez-vous au portail Azure et sélectionnez votre instance de serveur flexible Azure Database pour PostgreSQL.
  2. Sélectionnez Paramètres du serveur dans la section Paramètres du menu.
  3. Recherchez le paramètre pg_qs.query_capture_mode.
  4. Définissez la valeur sur top ou all, selon que vous souhaitez effectuer le suivi des requêtes de niveau supérieur ou également des requêtes imbriquées (qui s’exécutent à l’intérieur d’une fonction ou d’une procédure), puis cliquez sur Enregistrer. Patientez jusqu’à 20 minutes pour que le premier lot de données persiste dans la base de données azure_sys.

Activer l’échantillonnage d’attente du magasin des requêtes

  1. Recherchez le paramètre pgms_wait_sampling.query_capture_mode.
  2. Définissez la valeur sur all et cliquez sur Enregistrer.

Informations dans le magasin des requêtes

Le magasin des requêtes se compose de deux magasins :

  1. Un magasin des statistiques d’exécution pour conserver les informations sur les statistiques d’exécution des requêtes.
  2. Un magasin des statistiques d’attente pour conserver les informations sur les statistiques d’attente.

Les scénarios courants pour l’utilisation du magasin des requêtes comprennent :

  • Détermination du nombre de fois où une requête a été exécutée dans une fenêtre de temps donnée.
  • Comparaison de la durée d’exécution moyenne d’une requête sur plusieurs fenêtres de temps pour voir les variations importantes.
  • Identification des requêtes durables au cours des dernières heures.
  • Identification des N premières requêtes en attente de ressources.
  • Comprendre la nature des attentes pour une requête particulière.

Pour réduire l’utilisation de l’espace, les statistiques d’exécution du runtime dans le magasin des statistiques d’exécution sont agrégées pendant une fenêtre de temps configurable fixe. Les informations contenues dans ces magasins peuvent être interrogées à l’aide de vues.

Accéder aux informations du magasin des requêtes

Les données du magasin des requêtes sont stockées dans la base de données azure_sys sur votre instance de serveur flexible Azure Database pour PostgreSQL. La requête suivante retourne des informations sur les requêtes enregistrées dans le magasin des requêtes :

SELECT * FROM  query_store.qs_view;

Cette requête retourne également des informations sur les statistiques d’attente :

SELECT * FROM  query_store.pgms_wait_sampling_view;

Rechercher des requêtes d’attente

Les types d’événements d’attente combinent différents événements d’attente dans des compartiments par similarité. Le magasin des requêtes fournit le type d’événement d’attente, le nom de l’événement d’attente spécifique et la requête en question. Pouvoir mettre en corrélation ces informations d’attente avec les statistiques d’exécution de requête vous permet de mieux comprendre ce qui contribue aux caractéristiques de performances des requêtes.

Voici quelques exemples illustrant la façon d’obtenir plus d’informations dans votre charge de travail à l’aide des statistiques d’attente dans le magasin des requêtes :

Observation Action
Attentes de verrous élevés Vérifiez les textes de requêtes pour les requêtes affectées et identifiez les entités cibles. Recherchez dans le magasin des requêtes d’autres requêtes qui sont fréquemment exécutées et/ou ont une durée importante et modifient la même entité. Après avoir identifié ces requêtes, envisagez de changer la logique d’application pour améliorer l’accès concurrentiel, ou utilisez un niveau d’isolation moins restrictif.
Attentes d’E/S de mémoire tampon élevées Recherchez les requêtes comportant un grand nombre de lectures physiques dans le magasin des requêtes. Si elles correspondent aux requêtes avec des attentes d’E/S élevées, envisagez d’activer la fonctionnalité d’optimisation automatisée des index pour voir si elle peut recommander la création de certains index susceptibles de diminuer le nombre de lectures physiques pour ces requêtes.
Attentes de mémoire élevée Recherchez les requêtes qui consomment le plus de mémoire dans le magasin des requêtes. Ces requêtes retardent probablement davantage la progression des requêtes affectées.

Options de configuration

Lorsque le magasin des requêtes est activé, il enregistre les données dans des fenêtres d’agrégation de longueur déterminée par le paramètre de serveur pg_qs.interval_length_minutes (défini par défaut à 15 minutes). Pour chaque fenêtre, il stocke jusqu’à 500 requêtes distinctes. Les attributs qui distinguent l’unicité de chaque requête sont user_id (identificateur de l’utilisateur qui exécute la requête), db_id (identificateur de la base de données dans le contexte de laquelle la requête s’exécute) et query_id (valeur entière identifiant de manière unique la requête exécutée). Si le nombre de requêtes distinctes atteint 500 pendant l’intervalle configuré, 5 % des requêtes enregistrées sont libérées pour laisser la place à d’autres. Les requêtes libérées en premier sont celles qui ont été exécutées le moins de fois.

Les options suivantes sont disponibles pour la configuration des paramètres du Magasin des requêtes :

Paramètre Description Par défaut Plage
pg_qs.interval_length_minutes (*) Intervalle de capture du magasin des requêtes (en minutes). Définit la fréquence de persistance des données. 15 1 - 30
pg_qs.is_enabled_fs Utilisation interne uniquement : ce paramètre est utilisé comme commutateur de remplacement de fonctionnalité. S’il apparaît désactivé, le magasin des requêtes est désactivé malgré la valeur définie pour pg_qs.query_capture_mode. on on, off
pg_qs.max_plan_size Nombre maximal d’octets enregistrés à partir du texte du plan de requête par magasin des requêtes. Les plans plus longs sont tronqués. 7500 100 - 10000
pg_qs.max_query_text_length Longueur maximale de requête qui peut être enregistrée. Les requêtes plus longues sont tronquées. 6000 100 - 10000
pg_qs.parameters_capture_mode Indique si et quand capturer les paramètres positionnels de requête. capture_parameterless_only capture_parameterless_only, capture_first_sample
pg_qs.query_capture_mode Instructions à suivre. none none, top, all
pg_qs.retention_period_in_days Fenêtre de période de rétention en jours pour le magasin des requêtes. Les données plus anciennes sont automatiquement supprimées. 7 1 - 30
pg_qs.store_query_plans Indique si les plans de requête doivent être enregistrés dans le magasin des requêtes. off on, off
pg_qs.track_utility Indique si le magasin des requêtes doit suivre les commandes utilitaires. on on, off

(*) Paramètre statique du serveur qui nécessite un redémarrage du serveur pour qu’une modification de sa valeur prenne effet.

Les options suivantes s’appliquent spécifiquement aux statistiques d’attente :

Paramètre Description Par défaut Plage
pgms_wait_sampling.history_period Fréquence, en millisecondes, à laquelle les événements d’attente sont échantillonnés. 100 1 - 600000
pgms_wait_sampling.is_enabled_fs Utilisation interne uniquement : ce paramètre est utilisé comme commutateur de remplacement de fonctionnalité. Si elle apparaît comme off, l’échantillonnage d’attente est désactivé malgré la valeur définie pour pgms_wait_sampling.query_capture_mode. on on, off
pgms_wait_sampling.query_capture_mode Les instructions que l’extension pgms_wait_sampling doit suivre. none none, all

Remarque

pg_qs.query_capture_mode est prioritaire sur pgms_wait_sampling.query_capture_mode. Si pg_qs.query_capture_mode est none, le paramètre pgms_wait_sampling.query_capture_mode n’a pas d’effet.

Utilisez le portail Azure pour obtenir ou définir une valeur différente pour un paramètre.

Vues et fonctions

Vous pouvez interroger les informations enregistrées par le magasin des requêtes et les supprimer à l’aide de certaines vues et fonctions disponibles dans le schéma query_store de la base de données azure_sys. Quiconque dans le rôle public PostgreSQL peut utiliser ces vues pour afficher les données du magasin des requêtes. Ces vues sont disponibles uniquement dans la base de données azure_sys.

Les requêtes sont normalisées en examinant leur structure et en ignorant tout ce qui n’est pas sémantiquement significatif, comme les littéraux, les constantes, les alias ou les différences de casse.

Si deux requêtes sont sémantiquement identiques, même si elles utilisent des alias différents pour les mêmes colonnes et tables référencées, elles sont identifiées par le même query_id. Si deux requêtes diffèrent uniquement dans les valeurs littérales utilisées, elles sont également identifiées avec la même query_id. Pour les requêtes identifiées avec le même query_id, leur sql_query_text est celui de la requête exécutée en premier depuis le démarrage de l’activité d’enregistrement du magasin des requêtes, ou depuis la dernière fois que les données persistantes ont été ignorées à l’exécution de la fonction query_store.qs_reset.

Fonctionnement de la normalisation des requêtes

Voici quelques exemples pour essayer d’illustrer le fonctionnement de cette normalisation :

Supposons que vous créiez une table avec l’instruction suivante :

create table tableOne (columnOne int, columnTwo int);

Vous activez la collecte de données du Magasin des requêtes et un ou plusieurs utilisateurs exécutent les requêtes suivantes, dans l’ordre exact :

select * from tableOne;
select columnOne, columnTwo from tableOne;
select columnOne as c1, columnTwo as c2 from tableOne as t1;
select columnOne as "column one", columnTwo as "column two" from tableOne as "table one";

Toutes les requêtes précédentes partagent les mêmes query_id. Et le texte conservé par le Magasin des requêtes est celui de la première requête exécutée après l’activation de la collecte de données. Par conséquent, il serait select * from tableOne;.

L’ensemble de requêtes suivant, une fois normalisé, ne correspond pas au jeu de requêtes précédent, car la clause WHERE les rend sémantiquement différentes :

select columnOne as c1, columnTwo as c2 from tableOne as t1 where columnOne = 1 and columnTwo = 1;
select * from tableOne where columnOne = -3 and columnTwo = -3;
select columnOne, columnTwo from tableOne where columnOne = '5' and columnTwo = '5';
select columnOne as "column one", columnTwo as "column two" from tableOne as "table one" where columnOne = 7 and columnTwo = 7;

Toutefois, toutes les requêtes de ce dernier jeu partagent les mêmes query_id et le texte utilisé pour les identifier tous est celui de la première requête dans le lot select columnOne as c1, columnTwo as c2 from tableOne as t1 where columnOne = 1 and columnTwo = 1;.

Enfin, recherchez ci-dessous certaines requêtes qui ne correspondent pas au query_id de celles du lot précédent, et la raison pour laquelle elles ne correspondent pas :

Requête :

select columnTwo as c2, columnOne as c1 from tableOne as t1 where columnOne = 1 and columnTwo = 1;

Raison de ne pas correspondre : la liste des colonnes fait référence aux deux mêmes colonnes (ColonneUn et ColonneDeux), mais l’ordre dans lequel elles sont référencées est inversé, de columnOne, ColumnTwo dans le lot précédent à ColumnTwo, columnOne dans cette requête.

Requête :

select * from tableOne where columnTwo = 25 and columnOne = 25;

Raison de ne pas correspondre : Ordre dans lequel les expressions évaluées dans la clause WHERE sont référencées sont inversées de columnOne = ? and ColumnTwo = ? dans le lot précédent pour ColumnTwo = ? and columnOne = ? dans cette requête.

Requête :

select abs(columnOne), columnTwo from tableOne where columnOne = 12 and columnTwo = 21;

Raison de ne pas correspondre : la première expression de la liste de colonnes n’est plus columnOne, mais la fonction abs évaluée sur columnOne (abs(columnOne)), qui n’est pas sémantiquement équivalente.

Requête :

select columnOne as "column one", columnTwo as "column two" from tableOne as "table one" where columnOne = ceiling(16) and columnTwo = 16;

Raison de ne pas correspondre : la première expression de la clause WHERE n’évalue plus l’égalité de columnOne avec un littéral, mais avec le résultat de la fonction ceiling évaluée sur un littéral, ce qui n’est pas sémantiquement équivalent.

Vues

query_store.qs_view

Cette vue retourne toutes les données persistantes dans les tables de prise en charge du magasin des requêtes. Les données toujours enregistrées en mémoire pour la fenêtre de temps actuellement active ne sont pas visibles tant que la fenêtre de temps n’est pas terminée et que ses données volatiles en mémoire ne sont pas collectées et conservées sur des tables stockées sur le disque. Cette vue retourne une ligne différente pour chaque base de données distincte (db_id), l’utilisateur(-trice) (user_id) et la requête (query_id).

Nom Type Informations de référence Description
runtime_stats_entry_id bigint ID de la table runtime_stats_entries.
user_id oid pg_authid.oid OID de l’utilisateur(-trice) qui a exécuté l’instruction.
db_id oid pg_database.oid OID de la base de données dans laquelle l’instruction a été exécutée.
query_id bigint Code de hachage interne, calculé à partir de l’arborescence d’analyse de l’instruction.
query_sql_text varchar(10000) Texte d’une instruction représentative. Différentes requêtes ayant la même structure sont regroupées en clusters ; ce texte est le texte de la première des requêtes du cluster. La valeur par défaut de la longueur maximale du texte de la requête est de 6000, et peut être modifiée à l’aide du paramètre du Magasin des requêtes pg_qs.max_query_text_length. Si le texte de la requête dépasse cette valeur maximale, il est tronqué après les pg_qs.max_query_text_length premiers octets.
plan_id bigint ID du plan correspondant à cette requête.
start_time timestamp Les requêtes sont agrégées par fenêtres de temps. Le paramètre de serveur pg_qs.interval_length_minutes définit l’intervalle de temps de ces fenêtres (la valeur par défaut est de 15 minutes). Cette colonne correspond à l’heure de début de la fenêtre dans laquelle cette entrée a été enregistrée.
end_time timestamp Heure de fin correspondant à la fenêtre de temps pour cette entrée.
calls bigint Nombre de fois où la requête a été exécutée dans cette fenêtre temporelle. Notez que pour les requêtes parallèles, le nombre d’appels pour chaque exécution correspond à 1 pour le processus backend pilotant l’exécution de la requête, plus une unité par processus Worker backend lancé pour collaborer à l’exécution des branches parallèles de l’arborescence d’exécution.
total_time double précision Durée totale d’exécution de la requête, en millisecondes.
min_time double précision Durée minimale d’exécution de la requête, en millisecondes.
max_time double précision Durée maximale d’exécution de la requête, en millisecondes.
mean_time double précision Durée moyenne d’exécution de la requête, en millisecondes.
stddev_time double précision Écart type de la durée d’exécution de la requête, en millisecondes.
rows bigint Nombre total de lignes récupérées ou affectées par l’instruction. Notez que pour les requêtes parallèles, le nombre de lignes pour chaque exécution correspond au nombre de lignes renvoyées au client par le processus backend qui pilote l’exécution de la requête, plus la somme de toutes les lignes que chaque processus Worker backend, lancé pour collaborer à l’exécution des branches parallèles de l’arborescence d’exécution, renvoie au processus backend qui pilote l’exécution de la requête.
shared_blks_hit bigint Nombre total d’accès au cache de blocs partagés par l’instruction.
shared_blks_read bigint Nombre total de blocs partagés lus par l’instruction.
shared_blks_dirtied bigint Nombre total de blocs partagés modifiés par l’instruction.
shared_blks_written bigint Nombre total de blocs partagés écrits par l’instruction.
local_blks_hit bigint Nombre total d’accès au cache de blocs locaux par l’instruction.
local_blks_read bigint Nombre total de blocs locaux lus par l’instruction.
local_blks_dirtied bigint Nombre total de blocs locaux modifiés par l’instruction.
local_blks_written bigint Nombre total de blocs locaux écrits par l’instruction.
temp_blks_read bigint Nombre total de blocs temporaires lus par l’instruction.
temp_blks_written bigint Nombre total de blocs temporaires écrits par l’instruction.
blk_read_time double précision Durée totale passée par l’instruction à lire des blocs, en millisecondes (si track_io_timing est activé ; sinon, zéro).
blk_write_time double précision Durée totale passée par l’instruction à écrire des blocs, en millisecondes (si track_io_timing est activé ; sinon, zéro).
is_system_query booléen Détermine si le rôle avec user_id = 10 (azuresu) a exécuté la requête. Cet utilisateur dispose de privilèges de superutilisateur et est utilisé pour effectuer des opérations de plan de contrôle. Étant donné que ce service est un service PaaS managé, seule Microsoft fait partie du rôle de super-utilisateur(-trice).
query_type texte Type d’opération représenté par la requête. Les valeurs possibles sont les suivantes : unknown, select, update, insert, delete, merge, utility, nothing, undefined.
search_path texte Valeur de search_path définie au moment de la capture de la requête.
query_parameters texte Représentation textuelle d’un objet JSON avec les valeurs passées aux paramètres positionnels d’une requête paramétrisée. Cette colonne remplit uniquement sa valeur dans deux cas : 1) pour les requêtes non paramétrisées. 2) Pour les requêtes paramétrisées, lorsque pg_qs.parameters_capture_mode est défini sur capture_first_sample, et si le magasin des requêtes peut extraire les valeurs des paramètres de la requête au moment de l’exécution.
parameters_capture_status texte Type d’opération représenté par la requête. Les valeurs possibles sont succeeded (la requête n’était pas paramétrisée ou il s’agissait d’une requête paramétrisée et les valeurs ont été capturées avec succès), disabled (la requête était paramétrisée, mais les paramètres n’ont pas été capturés, car pg_qs.parameters_capture_mode était défini sur capture_parameterless_only), too_long_to_capture (la requête était paramétrisée, mais les paramètres n’ont pas été capturés, car la longueur du JSON résultant qui serait exposé dans la colonne query_parameters de cette vue, a été considéré comme excessivement long pour la persistance du magasin des requêtes), too_many_to_capture (la requête était paramétrisée, mais les paramètres n’ont pas été capturés, car le nombre total de paramètres était considéré comme excessif pour la persistance du magasin des requêtes), serialization_failed (la requête était paramétrisée, mais au moins l’une des valeurs passées en tant que paramètre n’a pas pu être sérialisée en texte).

query_store.query_texts_view

Cette vue retourne les données du texte des requêtes du Magasin des requêtes. Il y a une ligne pour chaque query_sql_text distinct.

Nom Type Description
query_text_id bigint ID de la table query_texts
query_sql_text varchar(10000) Texte d’une instruction représentative. Différentes requêtes ayant la même structure sont regroupées en clusters ; ce texte est le texte de la première des requêtes du cluster.
query_type smallint Type d’opération représenté par la requête. Dans la version de PostgreSQL <= 14, les valeurs possibles sont 0 (inconnu), 1 (sélectionner), 2 (mise à jour), 3 (insérer), 4 (supprimer), 5 (utilitaire), 6 (rien). Dans la version de PostgreSQL >= 15, les valeurs possibles sont 0 (inconnu), 1 (sélectionner), 2 (mise à jour), 3 (insérer), 4 (supprimer), 5 (fusionner), 6 (utilitaire), 7 (rien).

query_store.pgms_wait_sampling_view

Cette vue retourne les données des événements d’attente du Magasin des requêtes. Cette vue renvoie une ligne différente pour chaque base de données (db_id), utilisateur(-trice) (user_id), requête (query_id) et événement (event).

Nom Type Informations de référence Description
start_time timestamp Les requêtes sont agrégées par fenêtres de temps. Le paramètre de serveur pg_qs.interval_length_minutes définit l’intervalle de temps de ces fenêtres (la valeur par défaut est de 15 minutes). Cette colonne correspond à l’heure de début de la fenêtre dans laquelle cette entrée a été enregistrée.
end_time timestamp Heure de fin correspondant à la fenêtre de temps pour cette entrée.
user_id oid pg_authid.oid OID de l’utilisateur qui a exécuté l’instruction.
db_id oid pg_database.oid OID de la base de données dans laquelle l’instruction a été exécutée.
query_id bigint Code de hachage interne, calculé à partir de l’arborescence d’analyse de l’instruction.
event_type texte Type d’événement pour lequel le backend est en attente.
event texte Nom de l’événement d’attente si le backend est actuellement en attente.
calls entier Nombre de fois où le même événement a été capturé.

Remarque

Pour obtenir la liste des valeurs possibles dans les colonnes event_type et event de la vue query_store.pgms_wait_sampling_view, reportez-vous à la documentation officielle de pg_stat_activity et recherchez les informations faisant référence aux colonnes portant les mêmes noms.

query_store.query_plans_view

Cette vue retourne le plan de requête utilisé pour exécuter une requête. Il y a une ligne par ID de base de données distinct, ID d’utilisateur et ID de requête. Le magasin des requêtes enregistre uniquement les plans de requête pour les requêtes non utilitaires.

Nom Type Informations de référence Description
plan_id bigint Valeur de hachage du plan de requête normalisé produit par EXPLAIN. Il est sous forme normalisée, car il exclut les coûts estimés des nœuds de plan et l’utilisation des mémoires tampons.
db_id oid pg_database.oid OID de la base de données dans laquelle l’instruction a été exécutée.
query_id bigint Code de hachage interne, calculé à partir de l’arborescence d’analyse de l’instruction.
plan_text varchar(10000) Plan d’exécution de l’instruction donnée costs=false, buffers=false, and format=false. Sortie identique à celle produite par EXPLAIN.

Functions

query_store.qs_reset

Cette fonction ignore toutes les statistiques collectées jusqu’à présent par le magasin des requêtes. Il ignore les statistiques pour les fenêtres de temps déjà fermées, qui sont déjà conservées sur des tables sur disque. Il ignore également les statistiques de la fenêtre de temps actuelle, qui existe uniquement en mémoire. Seuls les membres disposant du rôle administrateur de serveur (azure_pg_admin) peuvent exécuter cette fonction.

query_store.staging_data_reset

Cette fonction supprime toutes les statistiques collectées en mémoire par le magasin des requêtes (c’est-à-dire les données en mémoire qui n’ont pas encore été transférées dans les tables sur disque qui assurent la persistance des données collectées pour le magasin des requêtes). Seuls les membres disposant du rôle administrateur de serveur (azure_pg_admin) peuvent exécuter cette fonction.

Mode Lecture seule

Lorsqu’une instance de serveur flexible Azure Database pour PostgreSQL est en mode lecture seule, par exemple lorsque le paramètre default_transaction_read_only est défini sur on, ou si le mode lecture seule est automatiquement activé en raison d’une capacité de stockage atteinte, le magasin des requêtes ne capture aucune donnée.

L’activation du magasin des requêtes sur un serveur qui contient des réplicas en lecture n’active pas automatiquement le magasin des requêtes sur les réplicas en lecture. Même si vous l’activez sur l’un des réplicas en lecture, le magasin des requêtes n’enregistre pas les requêtes exécutées sur les réplicas en lecture, car ils fonctionnent en mode lecture seule jusqu’à ce que vous les promouviez en mode principal.

Partager vos suggestions et bogues avec l’équipe produit Azure Database pour PostgreSQL.