DBAtlas · Atlas für Datenbankbetrieb

Datenbank ist langsam

Symptom

Anwendungsweite Langsamkeit; Abfragen dauern viel länger als üblich, und Benutzer beschweren sich.

1. Kläre zuerst, was genau langsam ist

Ist alles langsam oder nur eine bestimmte Abfrage/Maske? Wann hat es begonnen, und fällt das mit einem Deployment/Patch/Datenwachstum zusammen? Betrifft es das ganze System oder eine einzelne DB? So grenzt du die Suche auf eine Achse ein: CPU, I/O, Sperren oder Planänderung.

2. Aktive Sessions und Wait Events prüfen

Was läuft gerade, und was wartet? Ein dominierendes Wait Event (I/O, Lock, Log) zeigt auf den Engpass.

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. Auf Blockierungen prüfen

Die häufigste Ursache für Langsamkeit ist eine Session, die andere blockiert. Finde die blockierende Session und ermittle den Anfang der Kette.

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. Die teuersten Abfragen ermitteln

Finde die 10 Abfragen mit dem höchsten Ressourcenverbrauch. Meist stammen 90 % des Problems von einer Handvoll Abfragen.

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. Plan der verdächtigen Abfrage untersuchen

Hole dir EXPLAIN für die langsame Abfrage. Achte auf Full Table Scans, fehlende Indizes, schlechte Join-Reihenfolge oder veraltete Statistiken. Hat sich der Plan plötzlich geändert, erwäge, Statistiken zu sammeln.

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. Systemressourcen prüfen

Prüfe auf OS-Ebene CPU, I/O-Wartezeit (iowait), Speicher und Plattenbelegung. Prüfe die Cache Hit Ratio; ist sie niedrig, liegt eventuell ein Speicherengpass vor. Das Problem kann auch außerhalb der DB liegen (volle Platte, Noisy-Neighbor-VM).

7. Entscheiden: schnelle oder dauerhafte Lösung

Für sofortige Entlastung: die ausufernde Abfrage beenden, den fehlenden Index anlegen, Statistiken sammeln. Für eine dauerhafte Lösung: Abfrage/Index neu entwerfen, Speichereinstellungen korrigieren, Planstabilität sicherstellen (Baseline/Hint).

In DBAtlas öffnen →