Database Query Performance
Performa database sering menjadi bottleneck utama aplikasi web. Query yang lambat bisa membuat halaman yang secepat apapun terasa lemot.
Masalah N+1 Query
Ini adalah masalah paling umum dan paling merusak performa:
// BURUK — N+1 problem: 1 query untuk ambil posts,
// lalu 1 query PER post untuk ambil author
const posts = await db.query("SELECT * FROM posts"); // Query 1
for (const post of posts) {
// Query 2, 3, 4... N+1!
const author = await db.query(
"SELECT * FROM users WHERE id = ?", [post.author_id]
);
post.author = author;
}
// BAIK — 1 query dengan JOIN
const posts = await db.query(`
SELECT posts.*, users.name AS author_name
FROM posts
JOIN users ON users.id = posts.author_id
`);
Index — Kunci Performa Query
Index seperti daftar isi buku — daripada baca semua halaman, langsung ke halaman yang tepat.
-- Tanpa index: full table scan (baca semua row)
SELECT * FROM orders WHERE user_id = 123;
-- → Baca 1.000.000 row untuk cari 5 order
-- Dengan index: langsung ke row yang tepat
CREATE INDEX idx_orders_user_id ON orders(user_id);
SELECT * FROM orders WHERE user_id = 123;
-- → Baca 5 row langsung
EXPLAIN — Analisis Query
EXPLAIN SELECT * FROM orders
WHERE user_id = 123
ORDER BY created_at DESC;
-- Output yang perlu diperhatikan:
-- type: ALL (bad) vs ref/eq_ref (good)
-- rows: estimasi jumlah row yang dibaca
-- key: index yang digunakan (NULL = tidak ada)
-- Extra: "Using filesort" atau "Using temporary" = warning
Query Anti-patterns
-- BURUK: SELECT * mengambil semua kolom
SELECT * FROM users;
-- BAIK: Ambil kolom yang diperlukan saja
SELECT id, name, email FROM users;
-- BURUK: Fungsi di WHERE clause → tidak bisa pakai index
SELECT * FROM orders WHERE YEAR(created_at) = 2024;
-- BAIK: Range query yang bisa pakai index
SELECT * FROM orders
WHERE created_at >= "2024-01-01"
AND created_at < "2025-01-01";
-- BURUK: LIKE dengan wildcard di awal → full scan
SELECT * FROM products WHERE name LIKE "%laptop%";
-- BAIK: Gunakan Full Text Search
SELECT * FROM products
WHERE MATCH(name) AGAINST("laptop");
Query Cost Estimation
Cost = (jumlah row yang dibaca) × (biaya per operasi)
- Full scan: O(n) — linear dengan jumlah data
- Index scan: O(log n) — logaritmik
- Index lookup: O(1) — konstant (dengan unique index)