Ga naar de hoofdinhoud
{}
Terug naar alle artikels

Technisch artikel

Een trage MySQL-query onderzoeken met EXPLAIN

Gebruik een reproduceerbaar voorbeeld om een MySQL-queryplan te lezen, een indexvoorstel te onderzoeken en resultaten te vergelijken.

Door Jordy L’Oeuille3 minuten leestijd
  • SQL
  • MySQL
Queryvenster naast een stapsgewijs uitvoeringsplan met vergrootglas.
In dit artikel

Leg eerst de query en meetcontext vast

Een trage MySQL-query onderzoeken begint niet bij het toevoegen van een index. Bewaar de exacte SELECT, parameters, versie, bestaande indexen, datavolume en het moment waarop de vertraging optreedt. Onderscheid wachttijd door locks van rekenwerk en I/O. Het voorbeeld hieronder gebruikt acht fictieve bestellingen en dezelfde query vóór en na een kandidaat-index. Het is reproduceerbare uitleg, geen productiebenchmark en geen gemeten snelheidswinst. Gebruik de officiële documentatie van jouw databaseversie wanneer de uitvoer afwijkt.

Voer de demonstratie alleen in een testomgeving uit

Open een nieuwe verbinding met een afzonderlijke MySQL 8.4-testdatabase. Voer het hele blok in diezelfde sessie uit en stop bij de eerste fout. Er wordt alleen een sessiegebonden tijdelijke tabel gemaakt. Gebruik dit niet in productie en hergebruik geen bestaande sessie met een gelijknamige tabel. Sluit de verbinding om de tijdelijke tabel op te ruimen. EXPLAIN FORMAT=TRADITIONAL maakt de bedoelde uitvoervorm expliciet; de MySQL-uitvoer is geen SQLite- of SQL Server-plan.

Dezelfde SELECT vóór en na indexeringexamples/mysql-explain.sqlsql
-- Synthetic MySQL 8.4 demo. Use a NEW session in a separate test database.
-- Never run in production. Stop at the first error; close the session afterwards.
CREATE TEMPORARY TABLE cg_explain_orders (
    id INTEGER NOT NULL PRIMARY KEY,
    customer_id INTEGER NOT NULL,
    created_at DATETIME NOT NULL
);
INSERT INTO cg_explain_orders VALUES
    (1,42,'2026-08-31 23:59:59'), (2,42,'2026-09-01 00:00:00'),
    (3,42,'2026-09-01 12:00:00'), (4,42,'2026-09-01 12:00:00'),
    (5,42,'2026-09-02 00:00:00'), (6,7,'2026-09-01 12:00:00'),
    (7,42,'2026-09-01 23:59:59'), (8,42,'2026-09-02 00:00:01');

EXPLAIN FORMAT=TRADITIONAL
SELECT id, customer_id, created_at FROM cg_explain_orders
WHERE customer_id = 42
  AND created_at >= '2026-09-01 00:00:00'
  AND created_at < '2026-09-02 00:00:00'
ORDER BY created_at DESC, id DESC;

SELECT id, customer_id, created_at FROM cg_explain_orders
WHERE customer_id = 42
  AND created_at >= '2026-09-01 00:00:00'
  AND created_at < '2026-09-02 00:00:00'
ORDER BY created_at DESC, id DESC;

CREATE INDEX cg_explain_customer_date_id
ON cg_explain_orders(customer_id, created_at, id);

EXPLAIN FORMAT=TRADITIONAL
SELECT id, customer_id, created_at FROM cg_explain_orders
WHERE customer_id = 42
  AND created_at >= '2026-09-01 00:00:00'
  AND created_at < '2026-09-02 00:00:00'
ORDER BY created_at DESC, id DESC;

SELECT id, customer_id, created_at FROM cg_explain_orders
WHERE customer_id = 42
  AND created_at >= '2026-09-01 00:00:00'
  AND created_at < '2026-09-02 00:00:00'
ORDER BY created_at DESC, id DESC;
-- Both SELECTs should return IDs 7, 4, 3, 2. No timing claim follows from this.

Lees schattingen niet als meetresultaten

In traditionele EXPLAIN toont possible_keys mogelijke indexen en key de gekozen index. type beschrijft het toegangstype; rows en filtered helpen het geschatte werk te interpreteren. Extra bevat aanvullende informatie zoals sortering. Een genoemde index bewijst niet dat de hele query efficiënt is. Bij acht rijen kan een tabelscan voordeliger zijn. Een plan zonder de kandidaat-index is dus niet automatisch een fout. Vergelijk vooral de hypothese: kan de combinatie klant, datumbereik en sortering minder werk vragen?

Controleer correctheid vóór snelheid

Beide SELECTs moeten de ID’s 7, 4, 3 en 2 teruggeven. Record 2 test de inbegrepen startgrens; records 5 en 8 vallen buiten het halfopen interval. Record 6 hoort bij een andere klant. De gelijke tijdstippen van 3 en 4 worden door de extra ID-sortering ondubbelzinnig geordend. Voeg voor een echte workload ook NULL-waarden, lege resultaten, grote klanten en representatieve dataverdeling toe. Gelijke aantallen alleen bewijzen geen gelijke inhoud.

Meet de echte workload gecontroleerd

EXPLAIN ANALYZE voert een ondersteunde SELECT daadwerkelijk uit en levert runtime-informatie. Dat is nuttig, maar niet risicoloos op een zware productiequery. Gebruik een representatieve testomgeving en noteer versie, parameters, cachecondities en gelijktijdige belasting. Herhaal de meting en bekijk niet alleen het snelste resultaat. Meet ook schrijfbelasting en opslagkosten van de index. De hier beschreven fixture controleert logica, niet productieperformance. Maak geen algemene snelheidsclaim op basis van deze acht rijen.

Verder onderzoeken

Een queryplan is één deel van de diagnose. Hieronder vind je aanvullende uitleg en een afgebakende SQL-dienst. De demonstraties gebruiken fictieve gegevens, niet de resultaten van een klantproject. Deel bij een aanvraag alleen een probleembeschrijving en geanonimiseerde context; geen wachtwoorden, volledige dumps of persoonsgegevens.

Laatst bijgewerkt:

Technische context nodig voor je eigen project?

Codegenie helpt bij Laravel-applicaties, bestaande codebases, shared-hostingdeployments en technische verbeteringen.