Les requêtes actives les plus anciennes, également appelées requêtes les plus longues, répertorient les requêtes actives dans votre base de données, triées en fonction de leur durée d'exécution. L'analyse de ces requêtes permet d'identifier les causes des problèmes de latence du système et d'utilisation intensive du processeur au fur et à mesure qu'ils se produisent.
Spanner fournit une table intégrée, SPANNER_SYS.OLDEST_ACTIVE_QUERIES
, qui répertorie les requêtes en cours d'exécution, y compris les requêtes contenant des instructions LMD, triées par heure de début, par ordre croissant. Il n'inclut pas les requêtes de flux de modifications.
Si un grand nombre de requêtes sont en cours d'exécution, les résultats peuvent être
limitée à un sous-ensemble du nombre total de requêtes en raison des contraintes de mémoire que le système
impose la collecte de ces données. Par conséquent, Spanner
fournit un tableau supplémentaire, SPANNER_SYS.ACTIVE_QUERIES_SUMMARY
, qui indique
des statistiques récapitulatives pour toutes les requêtes actives (à l'exception des requêtes de flux de modifications).
Vous pouvez récupérer les informations de ces deux tables intégrées à l'aide d'instructions SQL.
Dans ce document, nous décrirons les deux tableaux, nous présentons des exemples de requêtes qui utilisent ces tableaux et, enfin, montrer comment les utiliser pour aider à atténuer les problèmes en raison de requêtes actives.
Disponibilité
Les données SPANNER_SYS
ne sont disponibles que via des interfaces SQL. Exemple :
Page Spanner Studio d'une base de données dans la console Google Cloud
La commande
gcloud spanner databases execute-sql
L'API
executeQuery
Les autres méthodes de lecture unique fournies par Spanner ne sont pas compatibles
SPANNER_SYS
OLDEST_ACTIVE_QUERIES
SPANNER_SYS.OLDEST_ACTIVE_QUERIES
renvoie la liste des requêtes actives triées par heure de début. Si un grand nombre de requêtes sont en cours d'exécution, les résultats peuvent être limités à un sous-ensemble du nombre total de requêtes en raison des contraintes de mémoire appliquées par Spanner sur la collecte de ces données. À
afficher le récapitulatif des statistiques de toutes les requêtes actives, voir
ACTIVE_QUERIES_SUMMARY
Schéma de la table
Nom de la colonne | Type | Description |
---|---|---|
START_TIME |
TIMESTAMP |
Heure de début de la requête. |
TEXT_FINGERPRINT |
INT64 |
L'empreinte est le hachage des opérations impliquées dans la transaction. |
TEXT |
STRING |
Texte de l'instruction de requête. |
TEXT_TRUNCATED |
BOOL |
"True" si le texte de la requête dans le champ TEXT est tronqué. Sinon, la valeur est "false". |
SESSION_ID |
STRING |
ID de la session qui exécute la requête. Elle est utilisée pour l'observabilité. |
QUERY_ID . |
STRING |
ID de la requête. Vous utilisez cet ID avec CALL cancel_query(query_id) pour annuler la requête. |
Exemples de requêtes
Vous pouvez exécuter les exemples d'instructions SQL suivants à l'aide des bibliothèques clientes, de la Google Cloud CLI ou de la console Google Cloud.
Répertorier les requêtes en cours les plus anciennes
La requête suivante renvoie la liste des requêtes les plus anciennes exécutées en fonction de l'heure de début de la requête.
SELECT start_time,
text_fingerprint,
text,
text_truncated,
session_id
FROM spanner_sys.oldest_active_queries
ORDER BY start_time ASC;
start_time | text_fingerprint | text | text_truncated | session_id |
---|---|---|---|---|
2020-07-18T07:52:28.225877Z | -3426560921851907385 | SELECT a.SingerId, a.AlbumId, a.TrackId, b.SingerId as b_id, b.AlbumId as b_albumid, b.TrackId as b_trackId FROM Songs as a CROSS JOIN Songs as b; | False | ACjbPvYsucrtcffHrRK6aObeIjZf12tSUwOsim-g1WC3IhqF4epzICCQR3GCHw |
2020-07-18T07:54:08.622081Z | -9206690983832919848 | SELECT a.SingerId, a.AlbumId, a.TrackId, a.SongName, s.FirstName, s.LastName FROM Songs as a JOIN Singers as s ON s.SingerId = a.SingerId WHERE STARTS_WITH(s.FirstName, 'FirstName') LIMIT 1000000; | False | ACjbPvaF3yKiNfxXFod2LPoFaXjKR759Bw1o34206vv0t7eOrD3wxZhu8U6ohQ |
2020-07-18T07:54:08.631744Z | -105437553161169030 | SELECT a.SingerId, a.AlbumId, a.TrackId, a.SongName, s.FirstName, s.LastName FROM Songs as a JOIN Singers as s ON s.SingerId = a.SingerId WHERE a.SingerId > 7 LIMIT 1000000; | False | ACjbPvanq3MesDNT98t64KdKAz3TlDZoCC-zgW-FJn91cJHuczQ_cOFN_Hdflw |
2020-07-18T07:54:08.720011Z | -9206690983832919848 | SELECT a.SingerId, a.AlbumId, a.TrackId, a.SongName, s.FirstName, s.LastName FROM Songs as a JOIN Singers as s ON s.SingerId = a.SingerId WHERE STARTS_WITH(s.FirstName, 'FirstName') LIMIT 1000000; | False | ACjbPvYIE2QHkhnmMXuAGpB4inK7yMnQjmYgQ9FoygKNaB5KCXu7Sf7f9aghYw |
2020-07-18T07:54:08.731006Z | 6561582859583559006 | SELECT a.SingerId, a.AlbumId, a.TrackId, a.SongName, s.FirstName, s.LastName FROM Songs as a JOIN Singers as s ON s.SingerId = a.SingerId WHERE a.SingerId > 10 LIMIT 1000000; | False | ACjbPvYNZ06N2YyvwV0YMlSRBNDtXBqZEK-iAAyPFnFcTmshPvzWkhr034ud7w |
Répertorier les 2 premières requêtes en cours les plus anciennes
Petite variante de la requête précédente, cet exemple renvoie les deux premières requêtes en cours les plus anciennes triées selon l'heure de début de la requête.
SELECT start_time,
text_fingerprint,
text,
text_truncated,
session_id
FROM spanner_sys.oldest_active_queries
ORDER BY start_time ASC LIMIT 2;
Sortie de la requête
start_time | text_fingerprint | text | text_truncated | session_id |
---|---|---|---|---|
2020-07-18T07:52:28.225877Z | -3426560921851907385 | SELECT a.SingerId, a.AlbumId, a.TrackId, b.SingerId as b_id, b.AlbumId as b_albumid, b.TrackId as b_trackId FROM Songs as a CROSS JOIN Songs as b; | False | ACjbPvYsucrtcffHrRK6aObeIjZf12tSUwOsim-g1WC3IhqF4epzICCQR3GCHw |
2020-07-18T07:54:08.622081Z | -9206690983832919848 | SELECT a.SingerId, a.AlbumId, a.TrackId, a.SongName, s.FirstName, s.LastName FROM Songs as a JOIN Singers as s ON s.SingerId = a.SingerId WHERE STARTS_WITH(s.FirstName, 'FirstName') LIMIT 1000000; | False | ACjbPvaF3yKiNfxXFod2LPoFaXjKR759Bw1o34206vv0t7eOrD3wxZhu8U6ohQ |
ACTIVE_QUERIES_SUMMARY
Comme son nom l'indique, la table intégrée, SPANNER_SYS.ACTIVE_QUERIES_SUMMARY
, affiche des statistiques récapitulatives pour toutes les requêtes actives. Comme indiqué dans le schéma suivant, les requêtes sont regroupées par âge en trois buckets (ou compteurs) datant de plus d'une seconde, de plus de 10 secondes et de plus de 100 secondes.
Schéma des tables
Nom de la colonne | Type | Description |
---|---|---|
ACTIVE_COUNT |
INT64 |
Nombre total de requêtes en cours d'exécution. |
OLDEST_START_TIME |
TIMESTAMP |
Limite supérieure de l'heure de début de la requête en cours la plus ancienne. |
COUNT_OLDER_THAN_1S |
INT64 |
Nombre de requêtes de plus d'une seconde. |
COUNT_OLDER_THAN_10S |
INT64 |
Nombre de requêtes de plus de 10 secondes. |
COUNT_OLDER_THAN_100S |
INT64 |
Nombre de requêtes de plus de 100 secondes. |
Une requête peut être comptabilisée dans plusieurs de ces buckets. Par exemple, si une requête a été exécutée pendant 12 secondes, elle est comptabilisée dans COUNT_OLDER_THAN_1S
et COUNT_OLDER_THAN_10S
, car elle remplit les deux critères.
Exemples de requêtes
Vous pouvez exécuter les exemples d'instructions SQL suivants à l'aide des bibliothèques clientes, de gcloud spanner ou de la console Google Cloud.
Récupérer un résumé des requêtes actives
La requête suivante renvoie des statistiques récapitulatives sur les requêtes en cours.
SELECT active_count,
oldest_start_time,
count_older_than_1s,
count_older_than_10s,
count_older_than_100s
FROM spanner_sys.active_queries_summary;
Sortie de la requête
active_count | oldest_start_time | count_older_than_1s | count_older_than_10s | count_older_than_100s |
---|---|---|---|---|
22 | 2020-07-18T07:52:28.225877Z | 21 | 21 | 1 |
Limites
Bien que l'objectif soit de vous fournir les insights les plus complets possibles, il existe des cas où les requêtes ne sont pas incluses dans les données renvoyées dans ces tables.
Les requêtes LMD (UPDATE/INSERT/DELETE) ne sont pas incluses si elles se trouvent dans la phase Apply mutations.
Une requête n'est pas incluse si elle est en cours de redémarrage en raison d'une erreur temporaire.
Les requêtes provenant de serveurs surchargés ou qui ne répondent pas ne sont pas prises en compte.
OLDEST_ACTIVE_QUERIES
ne peut pas être utilisé dans une transaction en lecture/écriture. Même dans une transaction en lecture seule, l'horodatage de la transaction est ignoré et elle renvoie toujours les données actuelles au moment de son exécution. Dans de rares cas, elle peut renvoyer une erreurABORTED
avec des résultats partiels. Dans ce cas, supprimez les résultats partiels et relancez la requête.
Utiliser les données des requêtes actives pour résoudre les problèmes d'utilisation élevée du processeur
Les statistiques des requêtes et les statistiques de transactions fournissent des informations utiles lors de la résolution de problèmes de latence dans une base de données Spanner. Ces outils fournissent des informations des requêtes déjà effectuées. Cependant, il est parfois nécessaire de connaître ce qui est en cours d'exécution dans le système. Par exemple, considérons le scénario suivant lequel l'utilisation du processeur est assez élevée et vous souhaitez répondre aux questions suivantes.
- Combien de requêtes sont exécutées actuellement ?
- Quelles sont ces requêtes ?
- Le nombre de requêtes exécutées pendant une longue période, c'est-à-dire au-delà de 100 secondes ?
- Quelle session exécute la requête ?
Avec les réponses aux questions précédentes, vous pouvez décider d'effectuer l'action suivante.
- Supprimer la session qui exécute la requête pour une résolution immédiate.
- Améliorer les performances des requêtes en ajoutant un index.
- Réduire la fréquence de la requête si elle est associée à une tâche d'arrière-plan périodique.
- Identifier l'utilisateur ou le composant qui émet la requête, et qui peut ne pas être autorisé à exécuter la requête.
Dans ce tutoriel, nous allons examiner nos requêtes actives des mesures à prendre, le cas échéant.
Récupérer un résumé des requêtes actives
Dans notre exemple de scénario, nous constatons que l'utilisation du processeur est supérieure à la normale. Nous allons donc exécuter la requête suivante pour renvoyer un résumé des requêtes actives.
SELECT active_count,
oldest_start_time,
count_older_than_1s,
count_older_than_10s,
count_older_than_100s
FROM spanner_sys.active_queries_summary;
La requête donne les résultats suivants.
active_count | oldest_start_time | count_older_than_1s | count_older_than_10s | count_older_than_100s |
---|---|---|---|---|
22 |
2020-07-18T07:52:28.225877Z |
21 |
21 |
1 |
Il s'avère qu'une requête s'exécute pour plus de 100 secondes. Ce résultat est inhabituel pour notre base de données et nous souhaitons l'étudier plus en détail.
Récupérer la liste des requêtes actives
Nous avons déterminé lors de l'étape précédente que nous exécutions une requête pendant plus de 100 secondes. Pour aller plus loin, nous exécutons la requête suivante pour renvoyer des informations supplémentaires sur les cinq requêtes en cours les plus anciennes.
SELECT start_time,
text_fingerprint,
text,
text_truncated,
session_id,
query_id
FROM spanner_sys.oldest_active_queries
ORDER BY start_time ASC LIMIT 5;
Dans cet exemple, nous avons exécuté la requête le 28 mars 2024 à environ 16h44m09s EDT, et elle a renvoyé les résultats suivants. (Vous devrez peut-être faire défiler la page horizontalement pour voir l'intégralité du résultat.)
start_time | text_fingerprint | text | text_truncated | session_id | query_id |
---|---|---|---|---|---|
28/03/2024 16:44:09.356939+00:00 | -2833175298673875968 | sélectionnez * parmi spanner_sys.oldest_active_queries | faux | ACjbPvYsucrtcffHrRK6aObeIjZf12tSUwOsim-g1WC3IhqF4epzICCQR3GCHw | 37190103859320827 |
2020-07-18T07:52:28.225877Z | -3426560921851907385 | SELECT a.SingerId, a.AlbumId, a.TrackId, b.SingerId as b_id, b.AlbumId as b_albumid, b.TrackId as b_trackId FROM Songs as a CROSS JOIN Songs as b; | faux | ACjbPvaF3yKiNfxXFod2LPoFaXjKR759Bw1o34206vv0t7eOrD3wxZhu8U6ohQ | 48946620525959556 |
La requête la plus ancienne (empreinte = -2833175298673875968
) est mise en surbrillance dans la
tableau. Le service est cher. CROSS JOIN
. Nous décidons d'agir.
Annuler une requête coûteuse
Dans cet exemple, nous avons trouvé une requête exécutant une CROSS JOIN
coûteuse. Nous décidons donc de l'annuler. Les résultats de requête reçus à l'étape
l'étape comprenait un query_id
. Nous pouvons exécuter la commande suivante :
CALL cancel_query(query_id)
pour GoogleSQL et
spanner.cancel_query(query_id)
pour PostgreSQL
annuler la requête.
GoogleSQL
CALL cancel_query(query_id)
PostgreSQL
CALL spanner.cancel_query(query_id)
Par exemple, dans l'exemple suivant, l'instruction CALL
annule une requête avec le
ID 37190103859320827
:
CALL cancel_query('37190103859320827')
Vous devez interroger la table spanner_sys.oldest_active_queries
pour vérifier que la requête est annulée.
Ce tutoriel explique comment utiliser SPANNER_SYS.OLDEST_ACTIVE_QUERIES
et
SPANNER_SYS.ACTIVE_QUERIES_SUMMARY
pour analyser les requêtes en cours d'exécution
si nécessaire sur toutes les requêtes qui contribuent à une utilisation élevée du processeur. Évidemment, il est toujours plus économique d'éviter les opérations coûteuses et de concevoir un schéma adapté à vos cas d'utilisation. Pour en savoir plus sur la construction d'instructions SQL qui s'exécutent efficacement, consultez la section Bonnes pratiques SQL.
Étape suivante
- Découvrez d'autres outils d'introspection.
- En savoir plus sur les autres informations stockées par Spanner pour chaque base de données dans les tables du schéma d'informations de la base de données.
- En savoir plus sur les bonnes pratiques SQL pour Spanner.