Ce document explique comment détecter et déboguer les points chauds dans votre base de données. Vous pouvez accéder aux statistiques sur les points chauds dans les fractionnements avec GoogleSQL et PostgreSQL.
Spanner stocke vos données sous forme d'espace clé contigu, ordonné par les clés primaires de vos tables et index. Une division est une plage de lignes provenant d'un ensemble de tables ou d'un index. Le début de la division est appelé début de la division. La limite de fractionnement définit la fin du fractionnement. La fraction inclut le début de la fraction, mais pas la limite de la fraction.
Dans Spanner, les hotspots sont des situations où trop de requêtes sont envoyées au même serveur, ce qui sature les ressources du serveur et peut entraîner des latences élevées. Les divisions concernées par les points chauds sont appelées divisions actives ou tièdes.
La statistique de point chaud d'une division (identifiée dans le système par CPU_USAGE_SCORE) est une mesure de la charge sur une division limitée par les ressources disponibles sur le serveur. Cette mesure est exprimée en pourcentage. Si plus de 50 % de la charge d'une division est limitée par les ressources disponibles, la division est considérée comme "chaude". Si 100 % de la charge sur une division est limitée, la division est considérée comme active. Ces fractionnements actifs peuvent également affecter la latence des requêtes qu'ils traitent.
La CPU_USAGE_SCORE d'un fractionnement peut rester constante ou varier au fil du temps en fonction de la charge de travail accédant au fractionnement et des modifications apportées aux limites du fractionnement.
En fonction des contraintes de ressources de partitionnement chaud et tiède, Spanner peut utiliser le partitionnement basé sur la charge pour répartir uniformément la charge dans l'espace de clés. Les splits "chaud" et "très chaud" peuvent être déplacés sur les serveurs de l'instance pour équilibrer la charge. Spanner effectue une répartition basée sur la charge en arrière-plan, ce qui minimise l'impact sur la latence. Toutefois, Spanner peut ne pas être en mesure d'équilibrer la charge, même après plusieurs tentatives de fractionnement, en raison d'antimodèles dans l'application. La colonne UNSPLITTABLE_REASONS dans les vues des statistiques fournit des raisons spécifiques pour lesquelles une division chaude ou tiède n'a pas pu être fractionnée davantage.
Par conséquent, les fractionnements persistants chauds ou tièdes qui durent au moins 10 minutes peuvent nécessiter un dépannage plus approfondi et des modifications potentielles de l'application, en particulier lorsque des UNSPLITTABLE_REASONS sont présents.
Les statistiques sur les divisions actives de Spanner vous aident à identifier les divisions où se produisent des hotspots et à comprendre pourquoi ils peuvent persister. Ces statistiques, combinées aux codes UNSPLITTABLE_REASONS, peuvent vous aider à diagnostiquer les actions à entreprendre pour résoudre les points chauds. Vous pouvez ensuite apporter les modifications nécessaires à votre application ou à votre schéma.
Accéder aux statistiques sur les partages rapides
Spanner fournit les statistiques de fractionnement à chaud dans le schéma SPANNER_SYS. Les données SPANNER_SYS sont disponibles via les interfaces GoogleSQL et PostgreSQL. Vous pouvez accéder à ces données de différentes manières :
- Page Spanner Studio d'une base de données dans la console Google Cloud .
- La commande
gcloud spanner databases execute-sql - La méthode
executeSqlouexecuteStreamingSql.
Les méthodes de lecture unique suivantes fournies par Spanner ne sont pas compatibles avec SPANNER_SYS :
- effectuer une lecture forte à partir d'une ou de plusieurs lignes d'une table ;
- effectuer une lecture non actualisée à partir d'une ou de plusieurs lignes d'une table ;
- lire à partir d'une ou de plusieurs lignes d'un index secondaire.
Statistiques sur les divisions les plus rapides
Vous pouvez utiliser les vues suivantes pour suivre les splits les plus populaires :
SPANNER_SYS.SPLIT_STATS_TOP_MINUTE: affiche les splits les plus populaires pendant des intervalles d'une minute.SPANNER_SYS.SPLIT_STATS_TOP_10MINUTE: affiche les fractionnements qui sont populaires à un moment donné d'un intervalle de 10 minutes.SPANNER_SYS.SPLIT_STATS_TOP_HOUR: affiche les fractionnements qui sont populaires à un moment donné d'un intervalle d'une heure.
Ces vues présentent les propriétés suivantes :
- Chaque vue contient les données correspondant à des intervalles de temps sans chevauchement de la durée spécifiée par le nom de la vue.
- Les intervalles sont définis selon l'heure réelle :
- Les intervalles d'une minute se terminent toutes les minutes.
- Les intervalles de 10 minutes se terminent à la 10e minute de l'heure, par exemple à 11:10:00 et 11:20:00.
- Les intervalles d'une heure se terminent toutes les heures.
- Après chaque intervalle, Spanner collecte les données de tous les serveurs, puis les met à disposition dans les vues
SPANNER_SYSpeu de temps après. Par exemple, à 11:59:30, les intervalles les plus récents disponibles pour les requêtes SQL sont les suivants :- 1 minute : de 11:58:00 à 11:58:59
- 10 minutes : de 11:40:00 à 11:49:59
- 1 heure : 10:00:00 – 10:59:59
- Spanner regroupe les statistiques par fractionnement.
- Chaque ligne contient des statistiques, y compris le pourcentage
CPU_USAGE_SCOREqui indique le degré de "chaleur" d'une division, pour chaque division pour laquelle Spanner enregistre des statistiques pendant l'intervalle spécifié. - La vue
SPANNER_SYS.SPLIT_STATS_TOP_MINUTEfournit des statistiques détaillées par minute. Utilisez cette vue pour déboguer en détail les événements récents. - Les vues
SPANNER_SYS.SPLIT_STATS_TOP_10MINUTEetSPANNER_SYS.SPLIT_STATS_TOP_HOURfournissent une vue agrégée à des intervalles de 10 minutes et d'une heure, respectivement. Utilisez ces vues pour analyser les tendances ou examiner les problèmes survenus au cours des derniers jours ou des dernières semaines. Pour en savoir plus sur l'agrégation, consultez Afficher l'agrégation des événements. - Si Spanner ne parvient pas à stocker toutes les divisions actives pendant l'intervalle, le système donne la priorité aux divisions ayant le pourcentage
CPU_USAGE_SCOREle plus élevé durant l'intervalle spécifié. Si aucun fractionnement n'est renvoyé, cela indique l'absence de fractionnements actifs.
Conservation des données
La quantité maximale de données que Spanner conserve pour chaque vue, à tout moment, est la suivante :
SPANNER_SYS.SPLIT_STATS_TOP_MINUTE: intervalles couvrant les 24 heures précédentes.SPANNER_SYS.SPLIT_STATS_TOP_10MINUTE: intervalles couvrant les quatre derniers jours.SPANNER_SYS.SPLIT_STATS_TOP_HOUR: intervalles couvrant les 30 derniers jours.
Vous ne pouvez pas augmenter ni diminuer ces périodes de conservation, et vous ne pouvez pas empêcher Spanner de collecter des statistiques sur les fractionnements à chaud.
- Pour supprimer les données statistiques, vous devez supprimer la base de données suivie ou attendre que les données statistiques ne soient plus conservées.
- Pour conserver les données statistiques pendant de plus longues périodes, copiez régulièrement les données des vues statistiques fractionnées "chaudes".
Afficher le schéma
Le tableau suivant présente le schéma des statistiques de fractionnement à chaud :
| Nom de la colonne | Type | Description |
|---|---|---|
INTERVAL_END |
TIMESTAMP |
Fin de l'intervalle de temps pendant lequel la division était à l'état tiède ou chaud. |
SPLIT_START |
STRING |
Clé de début de la plage de lignes dans la division. Le début de la division peut aussi être <begin>, ce qui indique le début de l'espace de clés. |
SPLIT_LIMIT |
STRING |
Clé de limite pour la plage de lignes dans la division. La clé de limite peut aussi être <end>, ce qui indique la fin de l'espace de clés. |
CPU_USAGE_SCORE |
INT64 |
Pourcentage CPU_USAGE_SCORE des répartitions. Un pourcentage de CPU_USAGE_SCORE de 50 % indique la présence de divisions chaudes ou très chaudes. |
AFFECTED_TABLES |
STRING ARRAY |
Il s'agit des tables dont les lignes peuvent être dans la division. |
UNSPLITTABLE_REASONS |
STRING ARRAY |
Identifie le type de points chauds présents que le fractionnement basé sur la charge ne peut pas atténuer, souvent en raison d'anti-modèles. La présence d'un motif indique qu'une intervention de l'utilisateur est probablement nécessaire, par exemple pour ajuster le schéma ou la charge de travail. Un tableau vide signifie qu'aucune condition non fractionnable n'a été détectée au cours de cet intervalle ou que la charge élevée a été trop éphémère pour que Spanner puisse déterminer si elle était non fractionnable. Pour en savoir plus, consultez les types UNSPLITTABLE_REASONS. |
Clés de début et de limite de fractionnement
Une division est une plage de lignes contiguës d'une base de données. Elle est définie par ses clés de début et de limite. Une division peut être une seule ligne, une plage de lignes étroite ou une plage de lignes large, et elle peut inclure plusieurs tables ou index.
Les colonnes SPLIT_START et SPLIT_LIMIT identifient les clés primaires d'une division chaude ou tiède.
Exemple de schéma
Le schéma suivant est un exemple de tableau pour les thèmes abordés sur cette page.
GoogleSQL
CREATE TABLE Users (
UserId INT64 NOT NULL,
FirstName STRING(MAX),
LastName STRING(MAX),
) PRIMARY KEY(UserId);
CREATE INDEX UsersByFirstName ON Users(FirstName DESC);
CREATE TABLE Threads (
UserId INT64 NOT NULL,
ThreadId INT64 NOT NULL,
Starred BOOL,
) PRIMARY KEY(UserId, ThreadId),
INTERLEAVE IN PARENT Users ON DELETE CASCADE;
CREATE TABLE Messages (
UserId INT64 NOT NULL,
ThreadId INT64 NOT NULL,
MessageId INT64 NOT NULL,
Subject STRING(MAX),
Body STRING(MAX),
) PRIMARY KEY(UserId, ThreadId, MessageId),
INTERLEAVE IN PARENT Threads ON DELETE CASCADE;
CREATE INDEX MessagesIdx ON Messages(UserId, ThreadId, Subject),
INTERLEAVE IN Threads;
PostgreSQL
CREATE TABLE users
(
userid BIGINT NOT NULL PRIMARY KEY,-- INT64 to BIGINT
firstname VARCHAR(max),-- STRING(MAX) to VARCHAR(MAX)
lastname VARCHAR(max)
);
CREATE INDEX usersbyfirstname
ON users(firstname DESC);
CREATE TABLE threads
(
userid BIGINT NOT NULL,
threadid BIGINT NOT NULL,
starred BOOLEAN, -- BOOL to BOOLEAN
PRIMARY KEY (userid, threadid),
CONSTRAINT fk_threads_user FOREIGN KEY (userid) REFERENCES users(userid) ON
DELETE CASCADE -- Interleave to Foreign Key constraint
);
CREATE TABLE messages
(
userid BIGINT NOT NULL,
threadid BIGINT NOT NULL,
messageid BIGINT NOT NULL PRIMARY KEY,
subject VARCHAR(max),
body VARCHAR(max),
CONSTRAINT fk_messages_thread FOREIGN KEY (userid, threadid) REFERENCES
threads(userid, threadid) ON DELETE CASCADE
-- Interleave to Foreign Key constraint
);
CREATE INDEX messagesidx ON messages(userid, threadid, subject), REFERENCES
threads(userid, threadid);
Imaginez que votre espace de clés se présente comme suit :
| CLÉ PRIMAIRE |
|---|
<begin> |
Users() |
Threads() |
Users(2) |
Users(3) |
Threads(3) |
Threads(3,"a") |
Messages(3,"a",1) |
Messages(3,"a",2) |
Threads(3, "aa") |
Users(9) |
Users(10) |
Threads(10) |
UsersByFirstName("abc") |
UsersByFirstName("abcd") |
<end> |
Exemple de fractionnement
Vous trouverez ci-dessous quelques exemples de fractionnement pour vous aider à comprendre à quoi ils ressemblent.
SPLIT_START et SPLIT_LIMIT peuvent indiquer la ligne d'un tableau ou d'un index, ou peuvent être <begin> et <end>, représentant les limites de l'espace de clés de la base de données. Les SPLIT_START et SPLIT_LIMIT peuvent également contenir des clés tronquées, qui sont des clés précédant toute clé complète dans le tableau. Par exemple, Threads(10) est un préfixe pour toute ligne Threads intercalée dans Users(10).
| SPLIT_START | SPLIT_LIMIT | AFFECTED_TABLES | EXPLICATION |
|---|---|---|---|
Users(3) |
Users(10) |
UsersByFirstName, Users, Threads, Messages et MessagesIdx |
La division commence à la ligne UserId=3 et se termine à la ligne précédant celle avec UserId = 10. La fraction contient les lignes de la table Users et toutes les lignes de ses tables entrelacées pour UserId=3 à 10. |
Messages(3,"a",1) |
Threads(3,"aa") |
Threads, Messages, MessagesIdx |
La division commence à la ligne avec UserId=3, ThreadId="a" et MessageId=1 et se termine à la ligne précédant celle avec la clé UserId=3 et ThreadsId = "aa". La répartition contient toutes les tables entre Messages(3,"a",1) et Threads(3,"aa"). Comme split_start et split_limit sont entrelacées dans la même ligne de tableau de premier niveau, la division contient les lignes de tables entrelacées entre le début et la limite. Consultez schemas-overview pour comprendre comment les tables entrelacées sont colocalisées. |
Messages(3,"a",1) |
<end> |
UsersByFirstName, Users, Threads, Messages et MessagesIdx |
La division commence dans la table des messages au niveau de la ligne avec la clé UserId=3, ThreadId="a" et MessageId=1. La division héberge toutes les lignes de split_start à <end>, la fin de l'espace de clés de la base de données. Toutes les lignes des tables suivant split_start, comme Users(4), sont incluses dans la division. |
<begin> |
Users(9) |
UsersByFirstName, Users, Threads, Messages et MessagesIdx |
La division commence à <begin>, au début de l'espace de clés de la base de données, et se termine à la ligne précédant la ligne Users avec UserId=9. La division contient donc toutes les lignes de la table précédant Users, toutes les lignes de la table Users précédant UserId=9 et les lignes de ses tables entrelacées. |
Messages(3,"a",1) |
Threads(10) |
UsersByFirstName, Users, Threads, Messages et MessagesIdx |
La division commence à Messages(3,"a", 1) intercalé dans Users(3) et se termine à la ligne précédant Threads(10). Threads(10) est une clé de fractionnement tronquée qui est un préfixe de n'importe quelle clé de la table Threads entrelacée dans Users(10). |
Users() |
<end> |
UsersByFirstName, Users, Threads, Messages et MessagesIdx |
La division commence à la clé de division tronquée de Users(), qui précède toute clé complète de la table Users. La division s'étend jusqu'à la fin de l'espace de clés possible dans la base de données. Les tables concernées couvrent donc la table Users, ses tables et index entrelacés, ainsi que toutes les tables qui peuvent apparaître après les utilisateurs. |
Threads(10) |
UsersByFirstName("abc") |
UsersByFirstName, Users, Threads, Messages et MessagesIdx |
La division commence à la ligne Threads avec UserId = 10 et se termine à l'index UsersByFirstName à la clé précédant "abc". |
Types UNSPLITTABLE_REASONS
Lorsque Spanner ne peut pas atténuer un point chaud par le biais d'une répartition basée sur la charge, la colonne UNSPLITTABLE_REASONS des vues SPLIT_STATS_TOP_* cite une ou plusieurs des raisons suivantes :
HOT_ROW
Description : la charge élevée est concentrée sur une seule ligne. Spanner ne peut pas ajouter de points de fractionnement dans une ligne individuelle.
Causes courantes :
- Opérations fréquentes et volumineuses (lectures, écritures ou mises à jour) sur une seule clé.
- Conceptions de schéma qui centralisent l'accès à une seule ligne.
Stratégies d'atténuation :
- Réduisez le nombre de requêtes par seconde pour le split chaud.
- Repensez le schéma pour répartir la charge. Par exemple, les compteurs de fragments sur plusieurs lignes.
- Consultez les bonnes pratiques de conception des schémas.
MOVING_HOT_SPOT
Description : la plage de clés qui connaît une charge élevée change au fil du temps, souvent de manière séquentielle. La division basée sur la charge est inefficace, car le point chaud se déplace avant que Spanner puisse diviser la plage précédemment concernée.
Causes courantes :
- Insertions avec une première partie de clé qui augmente ou diminue de manière monotone, comme un code temporel de validation.
- Lectures de points séquentielles dans l'espace de clés d'une table.
Stratégies d'atténuation :
- Évitez les clés qui augmentent ou diminuent de façon monotone pour la première partie de la clé primaire dans les charges de travail à écriture intensive. Pour obtenir des stratégies d'atténuation détaillées, consultez Bonnes pratiques de conception de schémas. Les techniques incluent l'utilisation d'UUID ou l'ajout d'un hachage de la clé.
LARGE_SCAN_HOT_SPOT
Description : le fractionnement est soumis à une charge élevée en raison d'opérations fréquentes ou gourmandes en ressources qui analysent une plage de clés. Cela peut inclure des lectures de plage (y compris les lectures émises dans le cadre d'une transaction) ou des requêtes. Spanner évite de fractionner excessivement les plages couvertes par ces opérations pour éviter une éventuelle dégradation des performances de ces analyses, qui peut se produire si les données sont trop fragmentées sur de nombreux petits fractionnements.
Causes courantes :
- Requêtes ou opérations de lecture exécutant des analyses de plages étendues sur des données auxquelles on accède fréquemment.
- Instructions LMD (
UPDATE,DELETE) avec des clauses WHERE qui nécessitent l'analyse de plages. - Absence d'index appropriés, ce qui entraîne des analyses de la table de base.
Stratégies d'atténuation :
- Optimisez les instructions SQL (
SELECT,UPDATE,DELETE) pour réduire le nombre de lignes analysées. - Créez des index appropriés pour prendre en charge les prédicats de requêtes et de LMD courants, en minimisant le nombre de lignes analysées.
UNISOLATABLE_HOT_ROW
Description : Spanner identifie une clé étroite à forte charge, mais ne peut pas l'isoler en insérant de nouveaux points de fractionnement, car aucun point de fractionnement approprié n'est disponible. Ce cas est semblable à HOT_ROW, mais SPLIT_START et SPLIT_LIMIT n'isolent pas complètement le point d'accès.
Causes courantes :
- Charge intense et localisée sur une ligne ou des lignes adjacentes partageant un préfixe de clé.
Stratégies d'atténuation :
- Analysez les modèles d'accès aux applications pour les clés dans les
SPLIT_STARTetSPLIT_LIMITsignalés. - Les stratégies d'atténuation chevauchent souvent
HOT_ROWet visent à réduire la charge opérationnelle directe sur la plage de clés étroite problématique.
UNSPECIFIED
Description : la division est soumise à une charge élevée et ne peut pas être divisée, mais la cause ne relève pas des autres catégories spécifiques. Cela peut se produire dans des scénarios de charge complexes ou en raison du comportement interne du système.
Stratégies d'atténuation :
- Examinez les charges de travail, les requêtes ou les transactions d'application qui accèdent aux tables de la répartition active (listées dans
AFFECTED_TABLES) et qui ont montré une augmentation de la charge. - Utilisez des outils tels qu'Insights sur les requêtes et Insights sur les transactions pour identifier les opérations coûteuses.
- Évaluez la charge de travail et assurez-vous d'utiliser les bonnes pratiques de conception de schémas et les bonnes pratiques SQL.
- Si le point d'accès persiste pendant plus de 10 minutes malgré les optimisations précédentes, ouvrez une demande d'assistance.
Afficher l'agrégation des événements
Les entrées des vues SPANNER_SYS.SPLIT_STATS_TOP_10MINUTE et SPANNER_SYS.SPLIT_STATS_TOP_HOUR représentent une agrégation des intervalles d'une minute dans leurs fenêtres respectives :
CPU_USAGE_SCORE : indique le CPU_USAGE_SCORE maximal enregistré pour le fractionnement dans n'importe quel intervalle d'une minute au cours de la période de 10 minutes ou d'une heure.
UNSPLITTABLE_REASONS : ce tableau est une union de tous les UNSPLITTABLE_REASONS uniques observés pour la fraction sur tous les intervalles d'une minute de la période.
Une séparation s'affiche dans ces vues si son CPU_USAGE_SCORE était de 50 % ou plus dans au moins l'un des intervalles de 1 minute.
Exemple d'agrégation
Examinez la répartition entre Users(101) et Users(102). Le tableau suivant présente ses entrées potentielles dans la vue MINUTE sur une période de 10 minutes, de 10:00:00 à 10:10:00 :
INTERVAL_END |
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
UNSPLITTABLE_REASONS |
|---|---|---|---|---|---|
| 10:01:00 | Utilisateurs(101) | Utilisateurs(102) | 60 | [Messages,Users,Threads] | [] |
| 10:02:00 | Utilisateurs(101) | Utilisateurs(102) | 95 | [Messages,Users,Threads] | [HOT_ROW] |
| 10:03:00 | Utilisateurs(101) | Utilisateurs(102) | 80 | [Messages,Users,Threads] | [HOT_ROW] |
| 10:04:00 | Utilisateurs(101) | Utilisateurs(102) | 55 | [Utilisateurs,Threads] | [] |
| 10:06:00 | Utilisateurs(101) | Utilisateurs(102) | 70 | [Utilisateurs,Threads] | [LARGE_SCAN_HOT_SPOT] |
| 10:07:00 | Utilisateurs(101) | Utilisateurs(102) | 65 | [Utilisateurs,Threads] | [LARGE_SCAN_HOT_SPOT] |
| 10:09:00 | Utilisateurs(101) | Utilisateurs(102) | 52 | [Utilisateurs,Threads] | [] |
L'entrée agrégée correspondante dans 10MINUTE pour l'intervalle se terminant à 10:10:00 pour cette fraction serait la suivante :
INTERVAL_END |
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
UNSPLITTABLE_REASONS |
|---|---|---|---|---|---|
| 10:10:00 | Utilisateurs(101) | Utilisateurs(102) | 95 | [Messages,Users,Threads] | [HOT_ROW, LARGE_SCAN_HOT_SPOT] |
CPU_USAGE_SCORE: 95 est la valeur maximale de la colonneCPU_USAGE_SCOREdans la vue d'une minute pour cette fraction de la période.UNSPLITTABLE_REASONS:[HOT_ROW, LARGE_SCAN_HOT_SPOT]correspond à l'union de tous les motifs uniques présents dans la colonneUNSPLITTABLE_REASONSde la vue "1 minute".
Cet exemple montre comment la vue 10MINUTE récapitule la charge la plus intense et tous les types de problèmes non fractionnables rencontrés au cours de la période. La vue HOUR suit la même logique d'agrégation sur une période de 60 minutes.
Trouver les splits les plus populaires
Vous pouvez utiliser l'instruction SQL suivante pour récupérer les statistiques de fractionnement à chaud. Vous pouvez exécuter ces instructions SQL à l'aide des bibliothèques clientes, de la Google Cloud CLI ou de la consoleGoogle Cloud .
SELECT
t.interval_end,
t.split_start,
t.split_limit,
t.cpu_usage_score,
t.affected_tables,
t.unsplittable_reasons
FROM
SPANNER_SYS.SPLIT_STATS_TOP_DURATION AS t
WHERE
-- Optional: Filter by a specific interval end time
-- t.interval_end = 'INTERVAL_END_TIME'
ORDER BY
t.interval_end DESC, t.cpu_usage_score DESC;
Remplacez les éléments suivants :
DURATION: choisissezMINUTE,10MINUTEouHOURen fonction de la période d'observation. Par exemple,SPANNER_SYS.SPLIT_STATS_TOP_HOUR.INTERVAL_END_TIME: remplacez par unTIMESTAMPde l'heure de fin de votre période d'observation. Par exemple,2072-06-08 08:30:00Z.
Interpréter les résultats de requête
Pour obtenir la liste complète des codes UNSPLITTABLE_REASONS et des diagnostics possibles, consultez Types de UNSPLITTABLE_REASONS.
Par exemple, le résultat de votre requête peut ressembler à ceci :
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
UNSPLITTABLE_REASONS |
|---|---|---|---|---|
| Threads(10) | Threads(10, "aa") | 100 | Messages,fils de discussion | [UNISOLATABLE_HOT_ROW] |
| Messages(631, "abc", 1) | Messages(631, "abc", 3) | 100 | Messages | [HOT_ROW] |
| Utilisateurs(620) | <end> | 100 | Messages,Utilisateurs,Fils de discussion | [MOVING_HOT_SPOT] |
| Utilisateurs(101) | Utilisateurs(102) | 90 | Messages,Utilisateurs,Fils de discussion | [HOT_ROW] |
| Utilisateurs(13) | Utilisateurs(76) | 82 | Messages,Utilisateurs,Fils de discussion | [LARGE_SCAN_HOT_SPOT] |
| Threads(12, "zebra") | Utilisateurs(14) | 76 | Messages,Utilisateurs,Fils de discussion | [] |
À partir de ces résultats, vous pouvez déduire les problèmes suivants :
- Threads(10) to Threads(10, "aa") : tendance à 100 % avec
[UNISOLATABLE_HOT_ROW]. Une seule clé, un préfixe de plage de clés dans la tableThreadsou une table imbriquée sont "chauds", et Spanner ne peut pas fractionner davantage la plage. - Messages(631, "abc", 1) à Messages(631, "abc", 3) : chaud à 100 % avec
[HOT_ROW]. La charge est concentrée sur les MessageId 1 et 2 pour cet utilisateur et ce thread. - Utilisateurs(620) à
<end>: chaud à 100 % avec[MOVING_HOT_SPOT]. Cela indique souvent un modèle d'insertions avec des ID utilisateur qui augmentent ou diminuent de manière monotone, ce qui entraîne une surchauffe persistante de la fin de l'espace de clé. - Utilisateurs(101) à Utilisateurs(102) : 90 % de chaleur avec
[HOT_ROW]. La charge est concentrée sur la ligne "Users" (ID utilisateur = 101) et ses enfants entrelacés. - Utilisateurs(13) à Utilisateurs(76) : 82 % de réponses positives avec
[LARGE_SCAN_HOT_SPOT]. Cela suggère des analyses fréquentes ou coûteuses pour cette plage d'ID utilisateur. - Threads(12, "zebra") vers Users(14) : utilisation à 76 %, température élevée. Aucune raison de non-fractionnement n'a été détectée dans cet intervalle. Spanner pourra peut-être encore le fractionner si la charge persiste ou augmente.
Résoudre les problèmes de points sensibles à l'aide des statistiques de division active
Cette section explique comment détecter et résoudre les problèmes liés aux points d'accès.
Sélectionner une période à examiner
Consultez les métriques de latence de votre base de données Spanner pour trouver la période pendant laquelle votre application a connu une latence et une utilisation du processeur élevées. Par exemple, il peut indiquer qu'un problème a commencé vers 22h50 le 18 mai 2072.
Rechercher les motifs de non-fractionnement
Comme Spanner équilibre la charge avec la répartition basée sur la charge, nous vous recommandons d'examiner les points d'accès qui persistent pendant plus de 10 minutes, en particulier s'ils ont une valeur UNSPLITTABLE_REASONS. La présence de UNSPLITTABLE_REASONS indique que Spanner ne peut pas fractionner le fractionnement actif. Des modifications du schéma ou de la charge de travail peuvent être nécessaires pour atténuer le point d'accès.
Vous pouvez interroger UNSPLITTABLE_REASONS comme indiqué dans l'exemple de requête suivant :
SELECT
reason,
COUNT(*) AS occurrences
FROM
SPANNER_SYS.SPLIT_STATS_TOP_MINUTE AS t,
UNNEST(t.unsplittable_reasons) AS reason
WHERE
t.cpu_usage_score >= 50
AND ARRAY_LENGTH(t.unsplittable_reasons) > 0
AND t.interval_end >= "2072-05-18T17:40:00Z" -- Start of window
AND t.interval_end <= "2072-05-18T17:50:00Z" -- End of window
GROUP BY
reason
ORDER BY
occurrences DESC;
La présence de UNSPLITTABLE_REASONS indique qu'un débogage supplémentaire est nécessaire.
Vous pouvez également surveiller les raisons pour lesquelles les instances ne peuvent pas être fractionnées à l'aide de Cloud Monitoring. La métrique à utiliser est unsplittable_reason_count. Pour en savoir plus, consultez Métriques Spanner.
Trouvez les fractions avec le CPU_USAGE_SCORE le plus élevé et leur UNSPLITTABLE_REASONS.
Pour cet exemple, nous exécutons la requête SQL suivante afin de trouver les plages de lignes avec le niveau CPU_USAGE_SCORE le plus élevé et leurs UNSPLITTABLE_REASONS correspondants :
GoogleSQL
SELECT t.split_start,
t.split_limit,
t.cpu_usage_score,
t.affected_tables,
t.unsplittable_reasons
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE t
WHERE t.cpu_usage_score >= 50
AND t.interval_end = "interval_end_date_time";
Remplacez interval_end_date_time par la date et l'heure de l'intervalle, au format AAAA-MM-JJTHH:MM:SSZ. Exemple : 2072-05-18T17:40:00Z.
PostgreSQL
SELECT t.split_start,
t.split_limit,
t.cpu_usage_score,
t.affected_tables,
t.unsplittable_reasons
FROM spanner_sys.split_stats_top_minute t
WHERE t.cpu_usage_score >= 50
AND t.interval_end = 'interval_end_date_time'::timestamptz;
Remplacez interval_end_date_time par la date et l'heure de l'intervalle, au format AAAA-MM-JJTHH:MM:SSZ. Exemple : 2072-05-18T17:40:00Z.
Le code SQL précédent génère la sortie suivante :
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
UNSPLITTABLE_REASONS |
|---|---|---|---|---|
Users(180) |
<end> |
85 |
Messages,Users,Threads |
[MOVING_HOT_SPOT] |
Users(24) |
Users(76) |
76 |
Messages,Users,Threads |
[HOT_ROW, LARGE_SCAN_HOT_SPOT] |
Threads(10) |
UsersByFirstName("abc") |
100 |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
[] |
À partir de ce tableau de résultats, nous constatons qu'il existe trois fractionnements à chaud, dont deux ne peuvent pas être fractionnés. Les points chauds avec UNSPLITTABLE_REASONS qui persistent dans le temps nécessitent un examen plus approfondi. Pour comprendre la signification de chaque motif et savoir comment l'atténuer, consultez Types de UNSPLITTABLE_REASONS.
Bonnes pratiques pour atténuer les points chauds
Remarque : Si votre charge a augmenté et que vous avez récemment augmenté la taille de votre instance, Spanner peut mettre quelques minutes à effectuer ses opérations d'équilibrage de charge avant que votre latence ne diminue.
Si l'équilibrage de charge ne réduit pas la latence, l'étape suivante consiste à identifier la cause des points chauds. Ensuite, vous pouvez soit réduire la charge de travail du point chaud, soit optimiser le schéma et la logique de l'application pour éviter les points chauds.
Identifier la cause
- Utilisez Insights sur les verrouillages et les transactions pour rechercher les transactions dont le temps d'attente de verrouillage est élevé et dont la clé de début de plage de lignes se trouve dans la division active.
- Utilisez Insights sur les requêtes pour rechercher les requêtes qui lisent à partir de la table contenant la répartition chaude et qui ont récemment augmenté la latence ou le ratio de latence/CPU.
- Utilisez Requêtes actives les plus anciennes pour rechercher les requêtes qui lisent à partir de la table contenant la répartition à chaud et qui présentent une latence plus élevée que prévu.
Voici quelques cas particuliers à surveiller :
- Vérifiez si la valeur TTL (Time To Live) a été activée récemment. Si les données anciennes sont réparties en de nombreuses divisions, le TTL peut augmenter les niveaux
CPU_USAGE_SCORElors des suppressions massives. Dans ce cas, le problème devrait se résoudre automatiquement une fois les suppressions initiales effectuées.
Optimiser la charge de travail
- Suivez les bonnes pratiques SQL. Pensez aux lectures obsolètes, aux écritures qui n'effectuent pas de lectures en premier ou à l'ajout d'index.
- Suivez les bonnes pratiques concernant les schémas. Assurez-vous que votre schéma est conçu pour gérer l'équilibrage de charge et éviter les points chauds.
Étapes suivantes
- Découvrez les bonnes pratiques de conception de schémas.
- En savoir plus sur Key Visualizer
- Consultez des exemples de conception de schémas.
- Découvrez comment utiliser le tableau de bord "Insights sur les fractionnements" pour détecter les points chauds.