Ketika aplikasi Bun mulai menghadapi query lambat, akar masalah umumnya terletak pada pencarian total tanpa dukungan index atau pagination. Artikel ini langsung menunjukkan cara mengidentifikasi query botol-botol tersebut, menambahkan index sesuai pola akses, dan menerapkan pagination yang tetap responsif saat data tumbuh.

Fokusnya pada pendekatan operasional: demonstrasi EXPLAIN untuk diagnosis, cara membuat index yang mendukung filter dan join, strategi pagination yang tidak memuat ulang data berlebihan, serta praktik monitoring untuk menghindari degradasi.

1. Diagnosa Query Lambat dengan EXPLAIN di Bun

Bun tidak mengubah dasar SQL, jadi diagnosis mulai dari EXPLAIN. Jalankan EXPLAIN pada query yang sering lambat untuk melihat apakah full table scan terjadi. Catatan penting: EXPLAIN tidak mempercepat langsung, tapi memberi tahu apakah index digunakan.

const result = await db.query(`EXPLAIN SELECT order_id, customer_id FROM orders WHERE created_at >= ?`, [startDate]);

Perhatikan kolom seperti type atau index pada engine yang digunakan. Jika hasil menunjukkan ALL atau tidak ada index, targetkan kolom yang dipakai di WHERE/ORDER BY untuk diindeks.

2. Membuat Index Efektif

Index berguna bila query menggunakan kolom tertentu secara konsisten. Misalnya query laporan berdasarkan customer_id dan rentang waktu:

SELECT order_id, total FROM orders WHERE customer_id = ? AND created_at BETWEEN ? AND ? ORDER BY created_at DESC;

Index tunggal pada customer_id mungkin tidak cukup karena filter waktu juga penting. Pertimbangkan composite index yang mencakup kedua kolom:

CREATE INDEX idx_orders_customer_created ON orders(customer_id, created_at DESC);

Composite index membantu engine memenuhi filter dan ORDER BY sekaligus. Hindari index berlebihan: setiap index menambah beban penulisan. Evaluasi akses dengan EXPLAIN setelah index dibuat untuk memastikan query memakai index tersebut.

Praktik terbaik pembuatan index

  • Prioritaskan kolom yang muncul di WHERE dulu, lalu kolom ORDER BY.
  • Batasi jumlah index agar tidak menghambat INSERT/UPDATE.
  • Gunakan covering index jika query hanya membaca beberapa kolom tertentu.
  • Perbarui statistik database setelah penambahan index agar optimizer memiliki data akurat.

3. Pagination yang Stabil

Pagination sederhana dengan OFFSET/ LIMIT menurun performanya ketika offset besar, karena engine masih membaca baris sebelumnya. Gunakan pagination berbasis cursor, misalnya menyimpan nilai created_at terakhir:

SELECT order_id, total, created_at FROM orders WHERE customer_id = ? AND created_at < ? ORDER BY created_at DESC LIMIT 20;

Cursor pagination menjaga query tetap memanfaatkan index karena filter tetap pada kolom yang terindeks. Pastikan field cursor bersifat deterministik agar tidak terjadi duplikat atau hilang data.

Pola pagination tambahan

  • Keyset pagination: Cocok untuk timeline/riwayat. Gunakan kolom waktu atau auto-increment sebagai anchor.
  • Pagination hybrid: Simpan snapshot ID terakhir di client dan fallback ke OFFSET jika anchor hilang.
  • Pastikan order konsisten saat mengurutkan: tambahkan id kedua jika created_at tidak unik.

4. Menjaga Performa saat Data Bertambah

Index perlu dijaga agar tetap sesuai pola akses saat dataset berubah. Terapkan monitoring sederhana:

  • Gunakan query profiling Bun (atau database) untuk mencatat query yang meningkat latensinya.
  • Periksa ukuran index dengan pg_stat_user_indexes (PostgreSQL) atau ekivalen SQLite/Bun.
  • Pantau penggunaan memori dan slow query log.

Ketika data tumbuh, pertimbangkan partitioning logis (misalnya berdasarkan tanggal) jika database mendukungnya agar scanning remain limited. Namun pahami trade-off: partition menambah kompleksitas maintenance dan tidak selalu diperlukan jika index sudah efektif.

5. Mitigasi Bottleneck SQL dan Praktik Bun

Pada Bun, Anda dapat menggunakan bun:sqlite atau driver eksternal. Pastikan pooling koneksi agar query paralel tidak menunggu terlalu lama. Jika menggunakan db.query langsung, hindari memanggil query berat di request utama tanpa caching.

Tips tambahan:

  • Cache hasil query yang jarang berubah di layer aplikasi atau CDN.
  • Gunakan prepared statement untuk menghindari parsing ulang.
  • Selalu cek EXPLAIN setelah perubahan index atau query besar.

Menggabungkan index yang tepat, pagination berbasis cursor, dan monitoring rutin membantu aplikasi Bun tetap skalabel saat base data tumbuh. Jangan lupa dokumentasikan pola akses agar tim lain mengerti alasan index dan paginasi yang diterapkan.