En este documento, se describe cómo detectar y depurar los puntos críticos de tu base de datos. Puedes acceder a estadísticas sobre los puntos calientes en las divisiones con GoogleSQL y PostgreSQL.
Spanner almacena tus datos como un espacio de claves contiguo, ordenado por las claves principales de tus tablas e índices. Una división es un rango de filas de un conjunto de tablas o un índice. El inicio de la división se denomina inicio de la división. El límite de división establece el final de la división. La división incluye el inicio de la división, pero no el límite de la división.
En Spanner, los hotspots son situaciones en las que se envían demasiadas solicitudes al mismo servidor, lo que satura los recursos del servidor y puede causar latencias altas. Las divisiones afectadas por los hotspots se conocen como divisiones activas o cálidas.
La estadística de hotspot de una división (identificada en el sistema como CPU_USAGE_SCORE) es una medición de la carga en una división que está restringida por los recursos disponibles en el servidor. Esta medición se expresa como un porcentaje. Si más del 50% de la carga en una división está restringida por los recursos disponibles, se considera que la división está activa. Si el 100% de la carga en una división está restringida, se considera que la división está activa. Estas divisiones activas también pueden afectar la latencia de las solicitudes que atienden.
El CPU_USAGE_SCORE de una división puede permanecer constante o variar con el tiempo según la carga de trabajo que accede a la división y los cambios en los límites de la división.
Según las restricciones de recursos de las divisiones activas y muy activas, es posible que Spanner use la división basada en la carga para distribuir de manera uniforme la carga en el espacio de claves. Las divisiones cálidas y calientes se pueden mover entre los servidores de la instancia para el balanceo de cargas. Spanner realiza la división basada en la carga en segundo plano, lo que minimiza el impacto en la latencia. Sin embargo, es posible que Spanner no pueda balancear la carga, incluso después de varios intentos de división, debido a antipatrones en la aplicación. La columna UNSPLITTABLE_REASONS en las vistas de estadísticas proporciona motivos específicos por los que una división activa o cálida no se pudo dividir más.
Por lo tanto, es posible que las divisiones persistentes cálidas o calientes que duran al menos 10 minutos requieran una solución de problemas adicional y posibles cambios en la aplicación, en especial cuando hay UNSPLITTABLE_REASONS.
Las estadísticas de divisiones activas de Spanner te ayudan a identificar las divisiones en las que se producen hotspots y a comprender por qué pueden persistir. Estas estadísticas, combinadas con los códigos UNSPLITTABLE_REASONS, pueden ayudarte a diagnosticar qué acciones debes realizar para resolver los puntos críticos. Luego, puedes realizar los cambios necesarios en tu aplicación o esquema.
Cómo acceder a las estadísticas de división de canciones
Spanner proporciona las estadísticas de división activa en el esquema SPANNER_SYS. Los datos de SPANNER_SYS están disponibles a través de las interfaces de GoogleSQL y PostgreSQL. Puedes acceder a estos datos de las siguientes maneras:
- La página de Spanner Studio de una base de datos en la consola de Google Cloud
- El comando
gcloud spanner databases execute-sql - El método
executeSqlo el métodoexecuteStreamingSql.
Los siguientes métodos de lectura única que proporciona Spanner no admiten SPANNER_SYS:
- Realizar una lectura sólida desde una o varias filas de una tabla
- Realizar una lectura inactiva desde una o varias filas en una tabla
- Leer desde una o varias filas en un índice secundario
Estadísticas de divisiones con mayor actividad
Usa las siguientes vistas para hacer un seguimiento de las divisiones más populares:
SPANNER_SYS.SPLIT_STATS_TOP_MINUTE: Muestra los tramos que son populares durante intervalos de 1 minuto.SPANNER_SYS.SPLIT_STATS_TOP_10MINUTE: Muestra los tramos que son populares durante cualquier parte de un intervalo de 10 minutos.SPANNER_SYS.SPLIT_STATS_TOP_HOUR: Muestra los cortes que son populares durante cualquier parte de un intervalo de 1 hora.
Estas vistas tienen las siguientes propiedades:
- Cada vista contiene datos de intervalos de tiempo no superpuestos de la duración que se especifica en el nombre de la vista.
- Los intervalos se basan en tiempos de reloj:
- Los intervalos de 1 minuto finalizan en el minuto.
- Los intervalos de 10 minutos finalizan en el décimo minuto de la hora, por ejemplo, 11:10:00, 11:20:00.
- Los intervalos de 1 hora finalizan en la hora.
- Después de cada intervalo, Spanner recopila datos de todos los servidores y, luego, los pone a disposición en las vistas de
SPANNER_SYSpoco después. Por ejemplo, a las 11:59:30 a.m., los intervalos más recientes disponibles para las consultas de SQL son los siguientes:- 1 minuto: de 11:58:00 a.m. a 11:58:59 a.m.
- 10 minutos: de 11:40:00 a.m. a 11:49:59 a.m.
- 1 hora: 10:00:00 a.m. a 10:59:59 a.m.
- Spanner agrupa las estadísticas por divisiones.
- Cada fila contiene estadísticas, incluido el porcentaje de
CPU_USAGE_SCORE, que indica qué tan caliente o tibia es una división, para cada división de la que Spanner captura estadísticas durante el intervalo especificado. - La vista
SPANNER_SYS.SPLIT_STATS_TOP_MINUTEofrece las estadísticas de división detalladas para cada minuto. Usa esta vista para depurar en detalle los eventos recientes. - Las vistas
SPANNER_SYS.SPLIT_STATS_TOP_10MINUTEySPANNER_SYS.SPLIT_STATS_TOP_HOURproporcionan una vista agregada en intervalos de 10 minutos y de una hora, respectivamente. Usa estas vistas para analizar tendencias o investigar problemas de los últimos días o semanas. Para obtener más información sobre la agregación, consulta Cómo ver la agregación de eventos. - Si Spanner no puede almacenar todas las divisiones activas durante el intervalo, el sistema prioriza las divisiones con el porcentaje de
CPU_USAGE_SCOREmás alto durante el intervalo especificado. Si no se devuelven divisiones, es un indicador de la ausencia de divisiones activas.
Retención de datos
La cantidad máxima de datos que Spanner conserva para cada vista, en cualquier momento, es la siguiente:
SPANNER_SYS.SPLIT_STATS_TOP_MINUTE: Intervalos que abarcan las 24 horas anteriores.SPANNER_SYS.SPLIT_STATS_TOP_10MINUTE: Intervalos que abarcan los 4 días anteriores.SPANNER_SYS.SPLIT_STATS_TOP_HOUR: Intervalos que abarcan los 30 días anteriores.
Estos períodos de retención no se pueden aumentar ni disminuir, y no puedes evitar que Spanner recopile estadísticas de divisiones activas.
- Para borrar los datos de estadísticas, debes borrar la base de datos que se está haciendo un seguimiento o esperar hasta que los datos de estadísticas se quiten de la retención.
- Para conservar los datos de estadísticas durante períodos más largos, copia periódicamente los datos de las vistas de estadísticas de división activa.
Ver esquema
En la siguiente tabla, se muestra el esquema de las estadísticas de división activa:
| Nombre de la columna | Tipo | Descripción |
|---|---|---|
INTERVAL_END |
TIMESTAMP |
Es el final del intervalo de tiempo durante el cual la división estuvo activa o caliente. |
SPLIT_START |
STRING |
Clave inicial del rango de filas en la división. El inicio de la división también puede ser <begin>, lo que indica el inicio del espacio de claves. |
SPLIT_LIMIT |
STRING |
Es la clave de límite del rango de filas en la división. La clave de límite también puede ser <end>, lo que indica el final del espacio de claves. |
CPU_USAGE_SCORE |
INT64 |
Es el porcentaje de CPU_USAGE_SCORE de las divisiones. Un porcentaje de CPU_USAGE_SCORE del 50% indica la presencia de divisiones activas o muy activas. |
AFFECTED_TABLES |
STRING ARRAY |
Son las tablas cuyas filas podrían estar en la división. |
UNSPLITTABLE_REASONS |
STRING ARRAY |
Identifica el tipo de hotspots presentes que la división basada en la carga no puede mitigar, a menudo debido a antipatrones. La presencia de cualquier motivo indica que es probable que se necesite la intervención del usuario, como ajustes del esquema o de la carga de trabajo. Un array vacío significa que no se detectaron condiciones no divisibles durante este intervalo o que la carga alta fue demasiado breve para que Spanner determinara si era indivisible. Consulta los tipos de UNSPLITTABLE_REASONS para obtener más detalles. |
Claves de inicio y límite de división
Una división es un rango de filas contiguas de una base de datos y se define por sus claves de inicio y límite. Una división puede ser una sola fila, un rango de filas estrecho o un rango de filas amplio, y puede incluir varias tablas o índices.
Las columnas SPLIT_START y SPLIT_LIMIT identifican las claves primarias de una división activa o inactiva.
Esquema de ejemplo
El siguiente esquema es una tabla de ejemplo para los temas de esta página.
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);
Imagina que tu espacio de claves se ve de la siguiente manera:
| PRIMARY KEY |
|---|
<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> |
Ejemplo de divisiones
A continuación, se muestran algunos ejemplos de divisiones para ayudarte a comprender cómo se ven.
SPLIT_START y SPLIT_LIMIT pueden indicar la fila de una tabla o un índice, o bien pueden ser <begin> y <end>, que representan los límites del espacio de claves de la base de datos. SPLIT_START y SPLIT_LIMIT también pueden contener claves truncadas, que son claves que preceden a cualquier clave completa en la tabla. Por ejemplo, Threads(10) es un prefijo para cualquier fila Threads intercalada en Users(10).
| SPLIT_START | SPLIT_LIMIT | AFFECTED_TABLES | EXPLICACIÓN |
|---|---|---|---|
Users(3) |
Users(10) |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La división comienza en la fila con UserId=3 y termina en la fila anterior a la fila con UserId = 10. La división contiene las filas de la tabla Users y todas las filas de sus tablas intercaladas para UserId=3 de 1 a 10. |
Messages(3,"a",1) |
Threads(3,"aa") |
Threads, Messages, MessagesIdx |
La división comienza en la fila con UserId=3, ThreadId="a" y MessageId=1, y termina en la fila anterior a la fila con la clave de UserId=3 y ThreadsId = "aa". La división contiene todas las tablas entre Messages(3,"a",1) y Threads(3,"aa"). Como split_start y split_limit están intercalados en la misma fila de la tabla de nivel superior, la división contiene las filas de las tablas intercaladas entre el inicio y el límite. Consulta schemas-overview para comprender cómo se ubican las tablas intercaladas. |
Messages(3,"a",1) |
<end> |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La división comienza en la tabla de mensajes en la fila con la clave UserId=3, ThreadId="a" y MessageId=1. La división aloja todas las filas desde split_start hasta <end>, el final del espacio de claves de la base de datos. Todas las filas de las tablas que siguen a split_start, como Users(4), se incluyen en la división. |
<begin> |
Users(9) |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La división comienza en <begin>, el inicio del espacio de claves de la base de datos, y termina en la fila anterior a la fila Users con UserId=9. Por lo tanto, la división tiene todas las filas de la tabla que preceden a Users y todas las filas de la tabla Users que preceden a UserId=9 y las filas de sus tablas intercaladas. |
Messages(3,"a",1) |
Threads(10) |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La división comienza en Messages(3,"a", 1) intercalada en Users(3) y termina en la fila anterior a Threads(10). Threads(10) es una clave de división truncada que es un prefijo de cualquier clave de la tabla de hilos intercalada en Users(10). |
Users() |
<end> |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La división comienza en la clave de división truncada de Users(), que precede a cualquier clave completa de la tabla Users. La división se extiende hasta el final del espacio de claves posible en la base de datos. Por lo tanto, affected_tables abarca la tabla Users, sus tablas y sus índices intercalados, y todas las tablas que podrían aparecer después de los usuarios. |
Threads(10) |
UsersByFirstName("abc") |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La división comienza en la fila Threads con UserId = 10 y termina en el índice UsersByFirstName en la clave que precede a "abc". |
UNSPLITTABLE_REASONS tipos
Cuando Spanner no puede mitigar un punto de acceso a través de la división basada en la carga, la columna UNSPLITTABLE_REASONS en las vistas de SPLIT_STATS_TOP_* cita uno o más de los siguientes motivos:
HOT_ROW
Descripción: La carga alta se concentra en una sola fila. Spanner no puede agregar puntos de división dentro de una fila individual.
Causas comunes:
- Operaciones frecuentes de gran volumen (lecturas, escrituras o actualizaciones) en una sola clave
- Diseños de esquemas que centralizan el acceso a una sola fila.
Estrategias de mitigación:
- Reduce las QPS en la división activa.
- Rediseña el esquema para distribuir la carga. Por ejemplo, contadores de fragmentos en varias filas.
- Revisa las prácticas recomendadas sobre el diseño del esquema.
MOVING_HOT_SPOT
Descripción: El rango de claves experimenta cambios de carga altos con el tiempo, a menudo de forma secuencial. La división basada en la carga no es eficaz, ya que el punto de acceso se reubica antes de que Spanner pueda dividir el rango afectado anteriormente.
Causas comunes:
- Inserciones con una parte de clave principal que aumenta o disminuye de forma monótona, como una marca de tiempo de confirmación
- Lecturas de puntos secuenciales en el espacio de claves de una tabla.
Estrategias de mitigación:
- Evita las claves que aumenten o disminuyan de forma monótona para la primera parte de la clave primaria en cargas de trabajo con uso intensivo de escritura. Para conocer estrategias de mitigación detalladas, consulta Prácticas recomendadas para el diseño de esquemas. Entre las técnicas, se incluyen el uso de UUID o la anteposición de un hash de la clave.
LARGE_SCAN_HOT_SPOT
Descripción: La división experimenta una carga alta debido a operaciones frecuentes o que requieren muchos recursos y que analizan un rango de claves. Esto puede incluir lecturas de rangos (incluidas las lecturas emitidas como parte de una transacción) o consultas. Spanner se abstiene de dividir en exceso los rangos que abarcan estas operaciones para evitar una posible degradación del rendimiento de estos análisis, lo que puede ocurrir si los datos se fragmentan demasiado en muchas divisiones pequeñas.
Causas comunes:
- Consultas u operaciones de lectura que ejecutan análisis de rango amplios en datos a los que se accede con frecuencia
- Declaraciones DML (
UPDATE,DELETE) con cláusulas WHERE que requieren rangos de análisis. - Ausencia de índices adecuados, lo que genera análisis de la tabla base
Estrategias de mitigación:
- Optimiza las instrucciones de SQL (
SELECT,UPDATE,DELETE) para reducir la cantidad de filas analizadas. - Crea índices adecuados para admitir predicados comunes de DML y consultas, y minimiza la cantidad de filas analizadas.
UNISOLATABLE_HOT_ROW
Descripción: Spanner identifica una clave estrecha con carga alta, pero no puede aislarla insertando nuevos puntos de división debido a la falta de un punto de división adecuado. Este caso es similar a HOT_ROW, pero SPLIT_START y SPLIT_LIMIT no aíslan por completo el hotspot.
Causas comunes:
- Carga intensa y localizada en una fila o en filas adyacentes que comparten un prefijo de clave.
Estrategias de mitigación:
- Analiza los patrones de acceso a la aplicación para las claves dentro de los objetos
SPLIT_STARTySPLIT_LIMITinformados. - Las estrategias de mitigación suelen superponerse con
HOT_ROWy se enfocan en reducir la carga operativa directa en el rango de claves estrecho problemático.
UNSPECIFIED
Descripción: La división experimenta una carga alta y no se puede dividir, pero la causa no se incluye en las otras categorías específicas. Esto puede ocurrir en situaciones de carga complejas o debido al comportamiento interno del sistema.
Estrategias de mitigación:
- Investiga las cargas de trabajo, las consultas o las transacciones de las aplicaciones que acceden a las tablas dentro de la división activa (que se enumeran en
AFFECTED_TABLES) que mostraron un aumento en la carga. - Usa herramientas como Estadísticas de consultas y Estadísticas de transacciones para identificar operaciones costosas.
- Evalúa la carga de trabajo y asegúrate de usar las prácticas recomendadas de diseño de esquemas y las prácticas recomendadas de SQL.
- Si el punto de acceso persiste durante más de 10 minutos a pesar de las optimizaciones anteriores, abre un caso de asistencia.
Visualiza la agregación de eventos
Las entradas en las vistas SPANNER_SYS.SPLIT_STATS_TOP_10MINUTE y SPANNER_SYS.SPLIT_STATS_TOP_HOUR representan una agregación de los intervalos de 1 minuto dentro de sus respectivas ventanas:
CPU_USAGE_SCORE: Muestra el CPU_USAGE_SCORE máximo registrado para la división en cualquier intervalo de 1 minuto dentro del período de 10 minutos o 1 hora.
UNSPLITTABLE_REASONS: Este array es una unión de todos los UNSPLITTABLE_REASONS únicos observados para la división en todos los intervalos de 1 minuto dentro de la ventana.
En estas vistas, aparece una división si su CPU_USAGE_SCORE fue del 50% o más en al menos uno de los intervalos de 1 minuto que la componen.
Ejemplo de agregación
Examina la división de Users(101) a Users(102). En la siguiente tabla, se muestran sus posibles entradas en la vista MINUTE durante un período de 10 minutos, de 10:00:00 a 10:10:00:
INTERVAL_END |
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
UNSPLITTABLE_REASONS |
|---|---|---|---|---|---|
| 10:01:00 | Usuarios(101) | Usuarios(102) | 60 | [Messages,Users,Threads] | [] |
| 10:02:00 | Usuarios(101) | Usuarios(102) | 95 | [Messages,Users,Threads] | [HOT_ROW] |
| 10:03:00 | Usuarios(101) | Usuarios(102) | 80 | [Messages,Users,Threads] | [HOT_ROW] |
| 10:04:00 | Usuarios(101) | Usuarios(102) | 55 | [Users,Threads] | [] |
| 10:06:00 | Usuarios(101) | Usuarios(102) | 70 | [Users,Threads] | [LARGE_SCAN_HOT_SPOT] |
| 10:07:00 | Usuarios(101) | Usuarios(102) | 65 | [Users,Threads] | [LARGE_SCAN_HOT_SPOT] |
| 10:09:00 | Usuarios(101) | Usuarios(102) | 52 | [Users,Threads] | [] |
La entrada agregada correspondiente en 10MINUTE para el intervalo que finaliza a las 10:10:00 para esta división sería la siguiente:
INTERVAL_END |
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
UNSPLITTABLE_REASONS |
|---|---|---|---|---|---|
| 10:10:00 | Usuarios(101) | Usuarios(102) | 95 | [Messages,Users,Threads] | [HOT_ROW, LARGE_SCAN_HOT_SPOT] |
CPU_USAGE_SCORE: 95 es el valor máximo de la columnaCPU_USAGE_SCOREen la vista de 1 minuto para esta división dentro del período.UNSPLITTABLE_REASONS:[HOT_ROW, LARGE_SCAN_HOT_SPOT]es la unión de todos los motivos únicos presentes en la columnaUNSPLITTABLE_REASONSde la vista de 1 minuto.
En este ejemplo, se muestra cómo la vista 10MINUTE resume la carga más intensa y todos los tipos de problemas indivisibles que se encontraron durante el período. La vista HOUR sigue la misma lógica de agregación en un período de 60 minutos.
Encuentra divisiones populares
Puedes usar la siguiente instrucción de SQL para recuperar estadísticas de divisiones activas. Puedes ejecutar estas instrucciones de SQL con las bibliotecas cliente, Google Cloud CLI o la consola deGoogle 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;
Reemplaza lo siguiente:
DURATION: EligeMINUTE,10MINUTEoHOURsegún el período de observación. Por ejemplo:SPANNER_SYS.SPLIT_STATS_TOP_HOUR.INTERVAL_END_TIME: Reemplázalo por unTIMESTAMPde la hora de finalización de tu período de observación. Por ejemplo,2072-06-08 08:30:00Z.
Interpreta los resultados de la búsqueda
Para obtener una lista completa de los códigos UNSPLITTABLE_REASONS y sus posibles diagnósticos, consulta Tipos de UNSPLITTABLE_REASONS.
Por ejemplo, el resultado de la consulta podría verse de la siguiente manera:
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
UNSPLITTABLE_REASONS |
|---|---|---|---|---|
| Hilos(10) | Threads(10, "aa") | 100 | Mensajes,Conversaciones | [UNISOLATABLE_HOT_ROW] |
| Messages(631, "abc", 1) | Messages(631, "abc", 3) | 100 | Mensajes | [HOT_ROW] |
| Usuarios(620) | <end> | 100 | Mensajes, usuarios y conversaciones | [MOVING_HOT_SPOT] |
| Usuarios(101) | Usuarios(102) | 90 | Mensajes, usuarios y conversaciones | [HOT_ROW] |
| Usuarios(13) | Usuarios(76) | 82 | Mensajes, usuarios y conversaciones | [LARGE_SCAN_HOT_SPOT] |
| Threads(12, "zebra") | Usuarios(14) | 76 | Mensajes, usuarios y conversaciones | [] |
A partir de estos resultados, podrías inferir los siguientes problemas:
- Threads(10) a Threads(10, "aa"): Hot en un 100% con
[UNISOLATABLE_HOT_ROW]. Una sola clave, un prefijo de rango de claves en la tablaThreadso una tabla intercalada están activos, y Spanner no puede dividir el rango más. - Messages(631, "abc", 1) a Messages(631, "abc", 3): Caliente al 100% con
[HOT_ROW]. La carga se concentra en los MessageId 1 y 2 para este usuario y subproceso. - Usuarios(620) a
<end>: Caliente al 100% con[MOVING_HOT_SPOT]. Esto suele indicar un patrón de inserciones con IDs de usuario que aumentan o disminuyen de forma monótona, lo que provoca que el final del espacio de claves esté persistentemente activo. - Usuarios(101) a Usuarios(102): Caliente en un 90% con
[HOT_ROW]. La carga se concentra en la única fila de Users UserId = 101 y sus elementos secundarios intercalados. - Usuarios(13) a Usuarios(76): Caliente en un 82% con
[LARGE_SCAN_HOT_SPOT]. Esto sugiere que se realizan análisis frecuentes o costosos en este rango de IDs de usuario. - Threads(12, "zebra") to Users(14): Cálido con un uso del 76%. No se detectaron motivos de no división en este intervalo. Spanner aún podría dividirlo si la carga persiste o aumenta.
Soluciona problemas de hotspots con estadísticas de divisiones activas
En esta sección, se describe cómo detectar y solucionar problemas relacionados con los puntos de acceso.
Selecciona un período para investigar
Verifica las métricas de latencia de tu base de datos de Spanner para encontrar el período en el que tu aplicación experimentó una latencia y un uso de CPU altos. Por ejemplo, podría mostrarte que un problema comenzó alrededor de las 10:50 p.m. del 18 de mayo de 2072.
Verificar si hay motivos de no división
A medida que Spanner equilibra la carga con la división basada en la carga, te recomendamos que investigues los hotspots que continúen durante más de 10 minutos, en especial si tienen UNSPLITTABLE_REASONS. La presencia de UNSPLITTABLE_REASONS indica que Spanner no puede dividir la división activa, y es posible que se necesiten cambios en el esquema o la carga de trabajo para mitigar el hotspot.
Puedes consultar UNSPLITTABLE_REASONS como se muestra en la siguiente consulta de ejemplo:
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 presencia de UNSPLITTABLE_REASONS indica que se necesita una depuración adicional.
También puedes supervisar los motivos por los que no se puede dividir el anuncio con Cloud Monitoring. La métrica que se debe usar es unsplittable_reason_count. Para obtener más información, consulta Métricas de Spanner.
Encuentra las divisiones con el CPU_USAGE_SCORE más alto y su UNSPLITTABLE_REASONS.
En este ejemplo, ejecutamos el siguiente código SQL para encontrar los rangos de filas con el nivel de CPU_USAGE_SCORE más alto y su UNSPLITTABLE_REASONS correspondiente:
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";
Reemplaza interval_end_date_time por la fecha y hora del intervalo con el formato AAAA-MM-DDTHH:MM:SSZ. Por ejemplo,
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;
Reemplaza interval_end_date_time por la fecha y hora del intervalo con el formato AAAA-MM-DDTHH:MM:SSZ. Por ejemplo,
2072-05-18T17:40:00Z.
El SQL anterior genera el siguiente resultado:
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 |
[] |
En esta tabla de resultados, podemos ver que hay tres divisiones activas y que dos de ellas no se pueden dividir. Los hotspots con UNSPLITTABLE_REASONS que persisten con el tiempo justifican una mayor investigación. Para comprender el significado de cada motivo y cómo mitigarlo, consulta Tipos de UNSPLITTABLE_REASONS.
Prácticas recomendadas para mitigar los puntos de acceso
Nota: Si tu carga aumentó y recientemente actualizaste tu instancia, es posible que Spanner tarde unos minutos en realizar sus operaciones de balanceo de cargas antes de que disminuya la latencia.
Si el balanceo de cargas no disminuye la latencia, el siguiente paso es identificar la causa de los puntos calientes. Después de eso, las opciones son reducir la carga de trabajo del hotspot o bien optimizar el esquema y la lógica de la aplicación para evitar los hotspots.
Identifica la causa
- Usa Lock & Transaction Insights para buscar transacciones que tengan un tiempo de espera de bloqueo alto en el que la clave de inicio del rango de filas esté dentro de la división activa.
- Usa Estadísticas de consultas para buscar consultas que lean desde la tabla que contiene la división activa y que hayan aumentado la latencia recientemente o tengan una proporción más alta de latencia en relación con la CPU.
- Usa Oldest Active Queries para buscar consultas que lean desde la tabla que contiene la división activa y que tengan una latencia más alta de lo esperado.
Estos son algunos casos especiales que debes tener en cuenta:
- Comprueba si se habilitó recientemente el tiempo de actividad (TTL). Si hay muchas divisiones de datos antiguos, el TTL puede aumentar los niveles de
CPU_USAGE_SCOREdurante las eliminaciones masivas. En este caso, el problema debería resolverse por sí solo una vez que se completen los borrados iniciales.
Optimiza la carga de trabajo
- Sigue las prácticas recomendadas sobre SQL. Considera las lecturas obsoletas, las escrituras que no realizan lecturas primero o la adición de índices.
- Sigue las prácticas recomendadas para el esquema. Asegúrate de que tu esquema esté diseñado para controlar el balanceo de cargas y evitar la generación de hotspots.
¿Qué sigue?
- Obtén más información sobre las prácticas recomendadas para el diseño de esquemas.
- Obtén más información sobre Key Visualizer.
- Consulta los ejemplos de diseños de esquema.
- Aprende a usar el panel de estadísticas divididas para detectar los puntos críticos.