DBAtlas · Atlas de operaciones de bases de datos

La base de datos está lenta

Síntoma

Lentitud en toda la aplicación; las consultas tardan mucho más de lo habitual y los usuarios se quejan.

1. Primero aclare qué es exactamente lo que está lento

¿Está todo lento o una consulta/pantalla concreta? ¿Cuándo empezó y coincide con un despliegue/parche/crecimiento de datos? ¿Afecta a todo el sistema o a una sola BD? Esto reduce la búsqueda a un eje: CPU, I/O, bloqueos o un cambio de plan.

2. Revise las sesiones activas y los wait events

¿Qué se está ejecutando y qué está esperando ahora mismo? Un wait event dominante (I/O, bloqueo, log) señala el cuello de botella.

Oracle

SELECT sid, username, status, event, sql_id FROM v$session WHERE status='ACTIVE' AND type='USER';

PostgreSQL

SELECT pid, state, wait_event_type, wait_event, query FROM pg_stat_activity WHERE state='active';

MySQL

SELECT id, user, command, time, state, info FROM information_schema.processlist WHERE command<>'Sleep' ORDER BY time DESC;

SQL Server

SELECT session_id, status, wait_type, wait_time, blocking_session_id FROM sys.dm_exec_requests WHERE session_id IN (SELECT session_id FROM sys.dm_exec_sessions WHERE is_user_process = 1);

MongoDB

db.currentOp({ active: true, secs_running: { $gt: 1 } })

Redis

SLOWLOG GET 10

3. Compruebe si hay bloqueos

La causa más común de lentitud es una sesión que bloquea a otras. Encuentre la sesión bloqueadora e identifique la cabeza de la cadena.

Oracle

SELECT blocking_session, sid, seconds_in_wait, event FROM v$session WHERE blocking_session IS NOT NULL;

PostgreSQL

SELECT pid, pg_blocking_pids(pid) AS blocked_by, query FROM pg_stat_activity WHERE cardinality(pg_blocking_pids(pid))>0;

MySQL

SELECT * FROM sys.innodb_lock_waits\G

SQL Server

SELECT session_id, blocking_session_id, wait_type FROM sys.dm_exec_requests WHERE blocking_session_id<>0;

4. Extraiga las consultas más costosas

Encuentre las 10 consultas que más recursos consumen. Normalmente el 90% del problema proviene de unas pocas consultas.

Oracle

SELECT sql_id, elapsed_time/1e6 sec, executions, sql_text FROM v$sql ORDER BY elapsed_time DESC FETCH FIRST 10 ROWS ONLY;

PostgreSQL

SELECT calls, total_exec_time, mean_exec_time, query FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 10;

MySQL

SELECT digest_text, count_star, sum_timer_wait/1e12 sec FROM performance_schema.events_statements_summary_by_digest ORDER BY sum_timer_wait DESC LIMIT 10;

SQL Server

SELECT TOP 10 total_elapsed_time/execution_count avg_us, execution_count, SUBSTRING(t.text,1,200) FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) t ORDER BY total_elapsed_time DESC;

5. Examine el plan de la consulta sospechosa

Obtenga el EXPLAIN de la consulta lenta. Busque full table scans, índices faltantes, un mal orden de joins o estadísticas obsoletas. Si el plan cambió de repente, considere recopilar estadísticas.

Oracle

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id', NULL, 'ALLSTATS LAST'));

PostgreSQL

EXPLAIN (ANALYZE, BUFFERS) <query>;

MySQL

EXPLAIN ANALYZE <query>;

SQL Server

SET STATISTICS PROFILE ON; <query>; SET STATISTICS PROFILE OFF;

MongoDB

db.my_collection.find({...}).explain('executionStats')  // COLLSCAN or IXSCAN?

6. Verifique los recursos del sistema

A nivel de SO, revise CPU, espera de I/O (iowait), memoria y uso de disco. Revise el cache hit ratio; si es bajo, puede haber un cuello de botella de memoria. El problema puede estar fuera de la BD (disco lleno, VM vecina ruidosa).

7. Decida: solución rápida o solución permanente

Para un alivio inmediato: termine la consulta descontrolada, agregue el índice faltante, recopile estadísticas. Para una solución permanente: rediseñe la consulta/índice, corrija la configuración de memoria, asegure la estabilidad del plan (baseline/hint).

Abrir en DBAtlas →