EXPLAIN ANALYZE SQL: Baca Rencana Eksekusi Query Kamu
TL;DR
EXPLAIN di SQL nunjukin rencana eksekusi yang bakal dipakai database buat jalanin query kamu, tanpa beneran ngejalaninnya. EXPLAIN ANALYZE ngejalanin query-nya dan ngasih waktu asli tiap langkah, jadi kamu bisa lihat persis di mana waktunya kebuang. Cara pakainya cukup tempel kata EXPLAIN ANALYZE di depan query kamu, lalu baca hasilnya dari baris paling dalam ke luar.
EXPLAIN di SQL nunjukin rencana eksekusi yang bakal dipakai database buat jalanin query kamu — tanpa beneran ngejalaninnya.
EXPLAIN ANALYZE ngejalanin query-nya, lalu ngasih waktu asli tiap langkah. Ini yang kamu butuh kalau query lambat dan kamu gak tau kenapa.
Nebak-nebak penyebab query lambat itu buang waktu. Query plan ngasih jawabannya dalam 2 detik.
Apa itu EXPLAIN di SQL?
Waktu kamu nulis query, kamu bilang apa yang kamu mau. Database yang mutusin gimana ngambilnya — tabel mana dibaca duluan, index dipakai atau gak, JOIN-nya pakai metode apa.
Keputusan itu namanya query plan. Dan EXPLAIN adalah cara kamu ngintip keputusan itu.
Cara pakainya cukup tempel di depan query:
EXPLAIN
SELECT kota, SUM(total) AS omzet
FROM transaksi
WHERE tanggal >= '2026-01-01'
GROUP BY kota;
Query-nya gak dijalanin. Kamu cuma dikasih rencananya.
Apa bedanya EXPLAIN dan EXPLAIN ANALYZE?
| EXPLAIN | EXPLAIN ANALYZE | |
|---|---|---|
| Query dijalanin? | Gak | Iya |
| Waktu yang ditampilkan | Estimasi (cost) | Waktu asli (actual time) |
| Jumlah baris | Tebakan | Tebakan + jumlah asli |
| Aman buat UPDATE/DELETE? | Aman | Bahaya — beneran jalan |
Baris terakhir itu penting. EXPLAIN ANALYZE DELETE FROM transaksi bakal beneran ngehapus datanya. Kalau kamu harus ngetes perintah yang ngubah data, bungkus di transaction:
BEGIN;
EXPLAIN ANALYZE UPDATE transaksi SET status = 'lunas' WHERE id < 100;
ROLLBACK;
Gimana cara baca query plan?
Ini hasil EXPLAIN ANALYZE dari tabel transaksi berisi 2,4 juta baris:
HashAggregate (cost=48250.11..48250.16 rows=5 width=40)
(actual time=8142.331..8142.336 rows=5 loops=1)
Group Key: kota
-> Seq Scan on transaksi (cost=0.00..44120.00 rows=826022 width=12)
(actual time=0.019..7011.442 rows=831405 loops=1)
Filter: (tanggal >= '2026-01-01'::date)
Rows Removed by Filter: 1568595
Planning Time: 0.184 ms
Execution Time: 8142.402 ms
Cara bacanya: dari dalam ke luar. Baris yang paling menjorok ke kanan itu yang jalan duluan.
Jadi urutannya:
Seq Scan on transaksi— database baca semua 2,4 juta baris satu per satu.Filter: tanggal >= 2026-01-01— dari situ dia buang 1.568.595 baris yang gak cocok.HashAggregate— sisanya digrupin per kota dan dijumlahin.
Angka yang paling penting: Execution Time: 8142 ms. Delapan detik.
Dan actual time=0.019..7011.442 di baris Seq Scan nunjukin 7 dari 8 detik itu habis cuma buat baca tabel.
Arti tiap angka
cost=0.00..44120.00— estimasi biaya. Angka pertama = biaya sampai baris pertama keluar. Angka kedua = biaya sampai semua baris keluar. Satuannya internal, bukan detik.rows=826022— tebakan database soal berapa baris yang bakal lolos.actual time=0.019..7011.442— waktu asli dalam milidetik.rows=831405di bagian actual — jumlah baris asli yang keluar.loops=1— berapa kali langkah ini diulang.
Bandingin rows estimasi (826.022) sama rows aktual (831.405). Beda tipis — berarti statistik tabelnya sehat.
Kalau bedanya jauh, misal estimasi 100 tapi aktual 500.000, itu alarm. Statistik kamu basi dan database salah nebak. Perbaiki dengan:
ANALYZE transaksi;
Node apa aja yang harus kamu kenal?
| Node | Artinya | Bagus atau jelek? |
|---|---|---|
Seq Scan | Baca semua baris tabel | Jelek di tabel besar, wajar di tabel kecil |
Index Scan | Loncat langsung ke baris yang cocok lewat index | Bagus |
Index Only Scan | Semua kolom yang dibutuhin ada di index | Paling bagus |
Bitmap Heap Scan | Kumpulin lokasi baris dulu, baru ambil | Bagus kalau hasilnya sedang |
Nested Loop | Buat tiap baris tabel A, cari di tabel B | Bagus kalau tabel A kecil, bencana kalau besar |
Hash Join | Bikin tabel hash di memori, lalu cocokin | Bagus buat JOIN besar |
Merge Join | Dua tabel diurutin lalu digabung | Bagus kalau dua-duanya udah terurut |
Sort | Ngurutin hasil | Mahal kalau datanya gak muat memori |
Yang paling sering jadi biang lambat: Seq Scan di tabel jutaan baris, dan Nested Loop yang loops-nya ribuan.
Kalau kamu lihat Sort Method: external merge Disk: 84200kB, itu artinya sorting-nya gak muat di memori dan tumpah ke disk. Lambat. Tambah work_mem atau kurangi data yang di-sort.
Contoh kasus: dari 8 detik jadi 40 milidetik
Balik ke query toko_berkah tadi. Execution Time 8.142 ms.
Penyebabnya jelas dari plan: Seq Scan, dan 1,5 juta baris dibuang oleh filter tanggal. Artinya database baca semua baris cuma buat buang sebagian besarnya.
Solusinya: kasih index di kolom yang difilter.
CREATE INDEX idx_transaksi_tanggal ON transaksi (tanggal);
Jalanin EXPLAIN ANALYZE lagi:
HashAggregate (cost=15230.42..15230.47 rows=5 width=40)
(actual time=41.219..41.223 rows=5 loops=1)
Group Key: kota
-> Bitmap Heap Scan on transaksi (actual time=8.914..28.106 rows=831405 loops=1)
Recheck Cond: (tanggal >= '2026-01-01'::date)
-> Bitmap Index Scan on idx_transaksi_tanggal (actual time=8.301..8.301 rows=831405 loops=1)
Planning Time: 0.211 ms
Execution Time: 41.284 ms
Seq Scan hilang, diganti Bitmap Index Scan. Execution Time turun dari 8.142 ms jadi 41 ms.
Itu 198 kali lebih cepat. Dari satu baris CREATE INDEX yang aku tulis setelah baca query plan-nya — bukan sebelum.
Ini poin utamanya. Tanpa EXPLAIN ANALYZE, aku mungkin nebak-nebak, ngubah GROUP BY, atau nambah index di kolom yang salah.
Sintaks di database lain
Perintahnya beda-beda tergantung database:
| Database | Perintah |
|---|---|
| PostgreSQL | EXPLAIN ANALYZE SELECT ... |
| MySQL 8 | EXPLAIN ANALYZE SELECT ... |
| SQLite | EXPLAIN QUERY PLAN SELECT ... |
| BigQuery | Tab Execution details di UI |
| SQL Server | SET STATISTICS PROFILE ON atau tombol Execution Plan |
Di PostgreSQL, versi lengkapnya kasih info lebih banyak lagi:
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT t.kota, p.kategori, SUM(t.total) AS omzet
FROM transaksi t
JOIN produk p ON p.id = t.produk_id
WHERE t.tanggal >= '2026-01-01'
GROUP BY t.kota, p.kategori
ORDER BY omzet DESC;
BUFFERS nunjukin berapa banyak data dibaca dari memori vs dari disk. Kalau angka read-nya besar, query kamu bolak-balik ke disk — dan itu lambat.
Detail lengkap semua opsinya ada di dokumentasi resmi PostgreSQL.
Kesalahan umum waktu baca query plan
1. Ngira cost itu detik
Cost 44120 bukan berarti 44 detik. Itu satuan internal buat ngebandingin rencana. Kalau kamu mau angka waktu, pakai EXPLAIN ANALYZE dan lihat actual time.
2. Anggap Seq Scan selalu jelek
Kalau query kamu emang butuh 80% baris tabel, Seq Scan justru lebih cepat dari Index Scan. Loncat-loncat lewat index buat 80% baris itu malah lebih mahal daripada baca berurutan.
Database sering udah bener soal ini. Yang perlu kamu waspadai: Seq Scan yang Rows Removed by Filter-nya jauh lebih besar dari rows yang keluar.
3. Lupa jalanin ANALYZE setelah data berubah banyak
Habis import 2 juta baris, statistik tabel kamu masih ngira tabelnya kecil. Database bakal pilih rencana yang salah. Jalanin ANALYZE nama_tabel.
4. Bikin index buat semua kolom
Index bikin SELECT cepat, tapi INSERT dan UPDATE jadi lambat — tiap tulis data, semua index-nya harus ikut diperbarui. Bikin index cuma di kolom yang sering muncul di WHERE, JOIN, atau ORDER BY.
5. Ngetes di database kecil
Query plan di tabel 1.000 baris beda sama di tabel 2 juta baris. Database bakal pilih Seq Scan di tabel kecil dan kamu gak bakal lihat masalahnya. Tes di data yang ukurannya mirip production.
Alur kerja yang aku pakai
- Query lambat? Jalanin
EXPLAIN ANALYZE. - Cari baris dengan
actual timepaling besar. - Cek node-nya:
Seq Scandi tabel besar?Nested Loopdengan loops ribuan? - Cek
Rows Removed by Filter. Kalau besar, kolom filternya butuh index. - Bandingin rows estimasi vs aktual. Meleset jauh? Jalanin
ANALYZE. - Perbaiki satu hal. Ukur lagi.
Satu perubahan, satu pengukuran. Kalau kamu ubah tiga hal sekaligus, kamu gak tau mana yang berhasil.
Buat teknik perbaikannya, baca 10 teknik optimasi query SQL. Dan kalau kamu masih baru sama konsep index, mulai dari glosarium index.
FAQ
Apa bedanya EXPLAIN dan EXPLAIN ANALYZE?
EXPLAIN cuma nunjukin rencananya. EXPLAIN ANALYZE beneran jalanin query-nya dan ngasih waktu asli tiap langkah.
Aman gak dijalanin di production?
Buat SELECT, aman. Buat UPDATE atau DELETE, bahaya — datanya beneran berubah. Bungkus di BEGIN dan ROLLBACK.
Apa artinya Seq Scan?
Database baca semua baris tabel satu per satu. Wajar di tabel kecil, biang lambat di tabel jutaan baris.
Kenapa estimasi rows meleset jauh?
Statistik tabelnya basi. Jalanin ANALYZE nama_tabel buat nyegerinnya.
Cost itu satuannya apa?
Satuan internal database, bukan detik. Cuma berguna buat ngebandingin rencana satu sama lain.
Penutup
Yang perlu kamu inget:
- Baca query plan dari dalam ke luar — yang paling menjorok kanan jalan duluan.
Execution Timedanactual timeitu angka nyata.costcuma perbandingan.Seq Scan+Rows Removed by Filteryang besar = kolom itu butuh index.
Ambil query paling lambat di kerjaan kamu, tempel EXPLAIN ANALYZE di depannya, dan lihat baris mana yang actual time-nya paling gede. Lima menit, dan kamu udah tau di mana masalahnya.
Mau latihan nulis dan ngetes query langsung di browser? Coba NgulikSQL — gratis, gak perlu install database.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel Terkait
7 SQL Client Gratis Terbaik buat Analis Data (2026)
Nggak perlu bayar buat nulis query. Ini 7 SQL client gratis yang beneran dipakai analis, plus kelebihan dan kekurangannya masing-masing.
SQL Style Guide: Cara Nulis Query yang Enak Dibaca Tim
Sepuluh aturan SQL style guide yang bikin query kamu kebaca sama tim — dan sama kamu sendiri 6 bulan lagi. Lengkap dengan contoh sebelum-sesudah.
Take-Home Test SQL Data Analyst: Contoh Soal + Cara Ngerjainnya
Contoh soal take-home test SQL yang beneran dipakai perusahaan, dikerjain step by step — dari baca soal, nulis query, sampai nyusun insight yang bikin recruiter nengok.