Belajar MongoDB - Deep Dive Indexing Strategies
Episode 12 of 21

Belajar MongoDB - Deep Dive Indexing Strategies

Memahami mengapa index mengubah pencarian dari collection scan O(N) menjadi index scan O(log N), mengenal tujuh tipe index MongoDB dari single field, compound dengan aturan ESR, multikey, hingga wildcard, TTL, unique, dan partial, serta kapan memakai masing-masing.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

Semua query yang kalian tulis sejauh ini bisa berjalan tanpa index — MongoDB cukup memindai seluruh dokumen. Masalahnya, "bisa berjalan" adalah standar yang sangat rendah. Saat collection tumbuh ke jutaan dokumen, query tanpa index menjadi lambat hingga tidak layak dipakai produksi. Inilah pekerjaan index: membuat MongoDB menemukan data tanpa harus melihat setiap dokumen.

Episode 12 adalah gerbang menuju MongoDB yang benar-benar performan. Roadmap-nya: pertama kita pahami mengapa index krusial, kedua single field index, ketiga compound index dengan aturan ESR, keempat multikey dan wildcard index, dan kelima index fungsional — TTL, unique, dan partial. Mari mulai.

Mengapa Indexing Krusial?

Tanpa index, MongoDB melakukan COLLSCAN (collection scan): membaca setiap dokumen satu per satu untuk mengecek kecocokan. Kompleksitasnya linear, O(N) — kalikan dua juta dokumen dengan waktu baca per dokumen, dan query menjadi sangat lambat.

Dengan index, MongoDB melakukan IXSCAN (index scan): mencari di struktur B-Tree yang terurut — seperti mencari kata di kamus, bukan membaca seluruh buku. Kompleksitasnya logaritmik, O(log N). Untuk 2 juta dokumen, perbedaannya bisa ratusan kali lipat:

Perbandingan kompleksitas pencarian
Collection scan  : O(N)   -> baca 2.000.000 dokumen
Index scan       : O(log N) -> baca sekitar 21 langkah

Prinsipnya mirip daftar isi di buku besar: index menyimpan salinan field tertentu dalam urutan terurut, beserta penunjuk ke lokasi dokumen aslinya. Query yang memakai field ber-index langsung menuju lokasi yang tepat tanpa membaca semua dokumen.

Index memakai ruang penyimpanan ekstra dan sedikit memperlambat insert/update (karena index harus dirawat), tapi keuntungan membaca yang diberikannya jauh melampaui biaya itu untuk workload baca yang dominan.

Single Field Index

Index paling sederhana: satu field, diurutkan ascending (1) atau descending (-1):

Membuat single field index
db.users.createIndex({ email: 1 })
 
db.products.createIndex({ price: -1 })

Untuk query yang menyaring atau mengurutkan berdasarkan satu field — pencarian email, sorting harga — index ini langsung bekerja. Arah sorting (1/-1) hampir tidak berpengaruh untuk pencarian kesetaraan, tapi penting untuk sort: index { price: -1 } bisa melayani sort({ price: -1 }) tanpa pengurutan tambahan di memory.

Compound Index

Konsep

Compound index menggabungkan beberapa field dalam satu index. Query yang menyaring atau mengurutkan kombinasi field — misal { category: "elektronik", price: { $lt: 500000 } } — bisa diselesaikan seluruhnya dengan satu index, jauh lebih cepat daripada dua index terpisah:

Membuat compound index
db.products.createIndex({ category: 1, price: -1 })

Urutan field dalam compound index sangat penting. Index { category: 1, price: -1 } melayani query yang menyaring category saja, category + price, atau mengurutkan kombinasi keduanya — tapi tidak efisien untuk query yang hanya menyaring price saja.

Aturan ESR (Equality, Sort, Range)

Untuk merancang compound index yang optimal, ikuti aturan ESR:

  1. E (Equality) — field yang disaring dengan kesetaraan, taruh di urutan pertama.
  2. S (Sort) — field yang dipakai sorting, di urutan kedua.
  3. R (Range) — field yang disaring dengan rentang ($lt, $gt), di urutan terakhir.
Compound index mengikuti aturan ESR
db.orders.createIndex({ userId: 1, createdAt: -1, total: 1 })

Index di atas dirancang untuk query { userId: "x", createdAt: { $gte: date }, total: { $gt: 100 } } dengan sort createdAt — field kesetaraan userId lebih dulu, lalu sort createdAt, dan rentang total di akhir. Ini memungkinkan MongoDB menggunakan satu index untuk filter sekaligus sort tanpa operasi tambahan.

Multikey Index

Saat field yang di-index berupa array, MongoDB otomatis membuat multikey index — index yang menyimpan setiap elemen array sebagai entri. Kalian tidak perlu melakukan apa pun khusus; cukup buat index biasa pada field array:

Multikey index pada field array
db.products.createIndex({ tags: 1 })

Index ini membuat query find({ tags: "best-seller" }) menjadi index scan, bukan collection scan. Multikey index terjadi otomatis saat MongoDB mendeteksi array pada field yang di-index. Catatan penting: multikey index tidak bisa menjadi komponen geospatial atau melakukan komposisi index pada beberapa field array sekaligus.

Wildcard Index

Wildcard index meng-index semua field dari sebuah dokumen tanpa harus mendaftar namanya satu per satu. Ini penyelamat untuk schema dinamis — misal produk dengan atribut yang tidak terprediksi:

Wildcard index untuk field dinamis
db.products.createIndex({ "$**": 1 })

Wildcard index menjamin field apa pun yang kalian tambahkan di masa depan otomatis ter-index. Tapi ia memakai lebih banyak ruang daripada index selektif — pakai sebagai jaring pengaman untuk dokumen dengan struktur dinamis, bukan pengganti index terarah pada field yang memang pasti dipakai query utama.

Index Fungsional

TTL Index: Auto-Delete Berbasis Waktu

TTL (Time To Live) index secara otomatis menghapus dokumen setelah durasi tertentu sejak nilai field tanggalnya. Sempurna untuk session data, log sementara, atau kode OTP:

TTL index menghapus dokumen setelah 3600 detik
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })

Setiap jam, thread monitor MongoDB menghapus dokumen yang createdAt-nya sudah lebih dari 3600 detik. Data "kadaluarsa" dibersihkan tanpa cron job manual. Perhatikan: field yang dipakai harus berisi Date, dan TTL tidak berlaku untuk collection capped.

Unique Index: Menjamin Keunikan

Unique index mencegah nilai duplikat pada field — aturan yang setara dengan PRIMARY KEY atau UNIQUE constraint di RDBMS:

Unique index pada email
db.users.createIndex({ email: 1 }, { unique: true })

Setelah index ini dibuat, dua dokumen dengan email sama akan ditolak — proteksi paling andal terhadap duplikasi data, lebih kuat daripada validasi aplikasi karena ditegakkan langsung oleh database.

Partial Index: Index untuk Subset Dokumen

Partial index hanya meng-index dokumen yang memenuhi partialFilterExpression. Menghemat ruang dan mempercepat insert karena dokumen di luar kriteria tidak di-index:

Partial index untuk user aktif saja
db.users.createIndex(
  { email: 1 },
  { unique: true, partialFilterExpression: { status: "active" } }
)

Contoh di atas menggabungkan unique + partial: email unik hanya dijamin di antara user berstatus active. User yang dinonaktifkan bisa memiliki email duplikat — perilaku yang kadang diinginkan untuk soft-delete user yang emailnya dipakai ulang.

Info

Aturan praktis jumlah index: untuk workload umum, mulailah dengan 2-5 index per collection yang benar-benar melayani query utama kalian. Setiap index tambahan memperlambat write dan memakan disk. Gunakan compound index ESR untuk melayani beberapa query sekaligus, dan jangan membuat index hanya karena "sepertinya perlu". Kita akan membuktikan nilai sebuah index dengan explain() di episode 13.

Warning

Waspadai indeks yang saling tumpang tindih. Compound index { a: 1, b: 1 } sudah melayani query yang hanya menyaring a — menambahkan index { a: 1 } lagi adalah pemborosan. Prinsip prefix: compound index bisa melayani query apa pun yang memakai prefiks field-nya. Audit index kalian secara berkala dan buang yang redundan.

Penutup

Pada episode 12 ini kalian telah memahami mengapa indexing mengubah performa dari collection scan O(N) menjadi index scan O(log N), serta mengenal tujuh tipe index: single field, compound dengan aturan ESR (Equality, Sort, Range), multikey yang otomatis untuk array, wildcard untuk schema dinamis, TTL untuk penghapusan otomatis berbasis waktu, unique untuk menjamin keunikan, dan partial untuk meng-index subset dokumen saja.

Inti yang harus dibawa pulang:

  • Index mengubah O(N) menjadi O(log N) — investasi paling berdampak di MongoDB.
  • Susun compound index dengan urutan ESR: Equality, Sort, Range.
  • Multikey index dibuat otomatis saat field array di-index.
  • TTL index membersihkan data kadaluarsa otomatis; unique index mencegah duplikat.
  • Jangan menumpuk index redundan — audit dan buang yang tidak terpakai.

Di episode 13 berikutnya kita membuktikan semua teori index dengan bukti nyata: Query Optimization & explain() Analysis. Kalian akan membaca execution plan, membedakan COLLSCAN dari IXSCAN, memahami winning plan versus rejected plans, serta mengaktifkan database profiler untuk menemukan slow queries di produksi. Sampai jumpa di episode 13!

Belajar MongoDB - Deep Dive Indexing Strategies | Belajar MongoDB