DBAtlas · Atlas d'exploitation des bases de données

La base est lente

Symptôme

Lenteur à l'échelle de l'application ; les requêtes prennent bien plus de temps que d'habitude et les utilisateurs se plaignent.

1. Précisez d'abord ce qui est lent

Tout est-il lent, ou une requête/un écran précis ? Quand cela a-t-il commencé, et cela coïncide-t-il avec un déploiement/un patch/une croissance des données ? Est-ce global ou limité à une seule base ? Cela ramène la recherche à un axe : CPU, E/S, verrouillage ou changement de plan.

2. Examinez les sessions actives et les événements d'attente

Qu'est-ce qui s'exécute et qu'est-ce qui attend en ce moment ? Un événement d'attente dominant (E/S, verrou, log) indique le goulet d'étranglement.

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. Recherchez les blocages

La cause la plus fréquente de lenteur est une session qui en bloque d'autres. Trouvez la session bloquante et identifiez la tête de la chaîne.

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. Extrayez les requêtes les plus coûteuses

Trouvez les 10 requêtes qui consomment le plus de ressources. En général, 90 % du problème vient d'une poignée de requêtes.

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. Examinez le plan de la requête suspecte

Obtenez l'EXPLAIN de la requête lente. Cherchez les full table scans, les index manquants, un mauvais ordre de jointure ou des statistiques obsolètes. Si le plan a changé soudainement, envisagez de collecter les statistiques.

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. Vérifiez les ressources système

Au niveau OS, vérifiez le CPU, l'attente E/S (iowait), la mémoire et l'utilisation disque. Vérifiez le cache hit ratio ; s'il est faible, il peut y avoir un goulet mémoire. Le problème peut se situer hors de la base (disque plein, VM voisine bruyante).

7. Décidez : correctif rapide ou définitif

Pour un soulagement immédiat : tuez la requête incontrôlée, ajoutez l'index manquant, collectez les statistiques. Pour un correctif définitif : revoyez la requête/l'index, corrigez les paramètres mémoire, assurez la stabilité des plans (baseline/hint).

Ouvrir dans DBAtlas →