Sepanjang section ini, semua query terasa instan — dan memang seharusnya begitu, karena katalog latihan kita hanya berisi enam document. Query yang sama pada enam juta document bisa memakan detik, dan yang membedakannya bukan sintaks, melainkan cara server menjalankannya: membaca seluruh collection, atau menumpang struktur data bernama index. MongoDB menyediakan explain() untuk melihat pilihan tersebut. Chapter penutup section ini memperkenalkan dua strategi eksekusi — COLLSCAN dan IXSCAN — tanpa membahas detail index itu sendiri: itu wilayah Section Indexing.
Peta materi Chapter ini:
explain()dan cara membacawinningPlan.stage.- Perbandingan
COLLSCANdenganIXSCANpada query yang sama. - Intuisi biaya: linear versus logaritmik.
explain(): Melihat Rencana Eksekusi #
Siapkan katalog standar:
use latihan_query
db.buku.drop()Output yang Dihasilkan:
switched to db latihan_query
truedb.buku.insertMany([
{ judul: "Laut Bercerita", penulis: "Leila S. Chudori", harga: 98000, stok: 12, kategori: "fiksi" },
{ judul: "Bumi", penulis: "Tere Liye", harga: 89000, stok: 25, kategori: "fiksi" },
{ judul: "Filosofi Teras", penulis: "Henry Manampiring", harga: 89000, stok: 18, kategori: "nonfiksi" },
{ judul: "Atomic Habits", penulis: "James Clear", harga: 115000, stok: 30, kategori: "nonfiksi" },
{ judul: "Rumah Kaca", penulis: "Tere Liye", harga: 72000, stok: 9, kategori: "fiksi" },
{ judul: "Kamus Bahasa Indonesia", penulis: "Badan Bahasa", harga: 55000, stok: 4, kategori: "referensi" }
])Output yang Dihasilkan:
{{OUT1}}Method explain() ditempelkan pada cursor dan mengembalikan rencana eksekusi alih-alih hasil query. Jalankan pada pencarian harga:
db.buku.find({ harga: 89000 }).explain()Output yang Dihasilkan:
{{OUT2}}Bagian yang perlu kita baca ada di queryPlanner.winningPlan. Mari kita bedah field-field kuncinya:
stage: 'COLLSCAN': singkatan collection scan — server membaca seluruh document satu per satu dan menguji filter pada masing-masing. Inilah satu-satunya pilihan, karena belum ada index padaharga.filter: { harga: { '$eq': 89000 } }: syarat yang diuji tiap document selama pemindaian.parsedQuerydancommand: bentuk query setelah ditafsirkan server —harga: 89000diterjemahkan menjadi$eq.rejectedPlans: []: kandidat rencana lain yang disingkirkan perencana — kosong karena tidak ada alternatif.
Pada enam document, COLLSCAN selesai dalam sekejap. Bayangkan ulang dengan satu juta document: seluruh juta itu dibaca untuk menemukan dua buku berharga 89000.
Index Mengubah Rencana: IXSCAN #
Buat satu index pada field harga — perintah lengkap pembuatan index kita bahas di Section Indexing; di sini cukup satu baris untuk melihat dampaknya pada rencana eksekusi:
db.buku.createIndex({ harga: 1 })Output yang Dihasilkan:
{{OUT3}}Jalankan explain() pada query yang persis sama:
db.buku.find({ harga: 89000 }).explain()Output yang Dihasilkan:
{{OUT4}}Rencana eksekusinya berubah total. Mari kita bedah:
stage: 'FETCH'denganinputStage: 'IXSCAN': eksekusi kini berjenjang — tahapIXSCANmemindai index untuk menemukan lokasi document, lalu tahapFETCHmengambil document aslinya dari disk.keyPattern: { harga: 1 }danindexName: 'harga_1': index yang dipilih, lengkap dengan pola dan nama otomatisnya.indexBounds: { harga: [ '[89000, 89000]' ] }: rentang kunci index yang diperiksa — tepat satu titik. Bandingkan denganCOLLSCANyang memeriksa seluruh collection;IXSCANhanya menyentuh kunci dalam rentang ini.
Setelah selesai mengamati, index latihan ini kita buang agar tidak memengaruhi chapter berikutnya:
db.buku.dropIndex({ harga: 1 })Output yang Dihasilkan:
{{OUT5}}Linear versus Logaritmik #
Rencana di atas menunjukkan dua strategi dengan karakter biaya berbeda. COLLSCAN bersifat linear — O(n): document yang dibaca tumbuh sebanding ukuran collection. IXSCAN menumpang struktur B-tree yang terurut: mencari satu nilai hanya butuh menelusuri kedalaman pohon, yang tumbuh logaritmik — O(log n). Ringkasnya:
Diagram di atas merangkum dua jalur yang kita uji nyata lewat explain(): tanpa index, seluruh document diperiksa satu per satu; dengan index, pencarian menyusuri pohon terurut lalu mengambil hanya document yang cocok. Perkiraan biayanya pada berbagai ukuran collection:
| Ukuran collection | COLLSCAN (document dibaca) | IXSCAN (kunci diperiksa, perkiraan) |
|---|---|---|
| 6 | 6 | ~3 |
| 10.000 | 10.000 | ~14 |
| 1.000.000 | 1.000.000 | ~20 |
| 100.000.000 | 100.000.000 | ~27 |
Selisih 10.000 dengan 14 terlihat sepele — dan memang pada data kecil, COLLSCAN sering kali lebih cepat karena tidak perlu melompat ke struktur lain. Kerugian baris kedua terhadap baris keempat itulah alasan performa query selalu berakhir pada pertanyaan index.
Menuju Section Indexing #
explain() yang kita pakai berjalan pada mode queryPlanner: ia menunjukkan rencana tanpa mengeksekusinya. Mode executionStats mengeksekusi query dan melaporkan angka nyata — jumlah document diperiksa, waktu per tahap — dan menjadi alat utama analisis performas; keduanya dibahas mendalam di Section Performance dan Optimization. Sebelum itu, Section Indexing menjawab pertanyaan yang pasti muncul: index jenis apa saja yang ada, bagaimana index majemuk bekerja, kapan index justru tidak dipakai, dan kenapa setiap index menambah biaya pada setiap operasi tulis. Semua query yang telah kita kuasai di section ini — filter, projection, sort, sampai regex prefix — akan kembali muncul di sana sebagai bahan analisis.
Terakhir, karena section ini tuntas, bersihkan database latihan:
db.dropDatabase()Output yang Dihasilkan:
{{OUT6}}Rangkuman #
explain()mengembalikan rencana eksekusi;winningPlan.stageadalah tempat membaca strategi server.COLLSCANmembaca seluruh collection — wajar pada data kecil, mahal secara linear pada data besar.IXSCANmenumpang B-tree terurut denganindexBoundssempit, laluFETCHmengambil document — biaya logaritmik.- Mode
executionStatsdan desain index yang tepat dibahas di Section Performance dan Section Indexing.