Single Index vs Composite Index di MySQL: Kapan Pakai yang Mana?

Hari ini saya belajar tentang perbedaan single index dan composite index di MySQL. Topik ini sering muncul saat optimasi query yang lambat — saya sendiri kadang bingung kapan harus pakai yang mana. Catatan ini saya rangkum dari beberapa sumber, termasuk mysqltutorial.org, dev.to, dan datacamp.com. Semoga bermanfaat.

Apa itu Single Index?

Single index adalah indeks yang dibuat pada satu kolom saja. Ini adalah jenis indeks yang paling sederhana dan paling sering digunakan. Contohnya:

-- Single index pada kolom email
CREATE INDEX idx_users_email ON users(email);

-- Single index pada kolom status
CREATE INDEX idx_orders_status ON orders(status);

Single index cocok untuk query yang hanya melakukan filter pada satu kolom, seperti:

SELECT * FROM users WHERE email = 'rudy@example.com';
SELECT * FROM orders WHERE status = 'pending';

Kelebihannya: sederhana, mudah dipahami, dan index maintenance-nya ringan. Kekurangannya: tidak bisa membantu query yang filter pada banyak kolom sekaligus.

Apa itu Composite Index?

Composite index (atau multiple-column index) adalah indeks yang dibuat pada dua kolom atau lebih. MySQL memungkinkan composite index hingga 16 kolom. Contohnya:

-- Composite index pada kolom (status, created_at)
CREATE INDEX idx_orders_status_created ON orders(status, created_at);

-- Composite index pada kolom (user_id, product_id, quantity)
CREATE INDEX idx_order_items_composite ON order_items(user_id, product_id, quantity);

Composite index sangat powerful karena bisa melayani banyak jenis query dengan satu indeks saja. Tapi ada aturan penting yang harus dipahami: leftmost prefix rule.

Leftmost Prefix Rule: Aturan Terpenting

Ini adalah konsep kunci yang harus dipahami saat menggunakan composite index. MySQL hanya bisa menggunakan composite index jika query melakukan filter pada kolom-kolom yang dimulai dari kolom paling kiri (leftmost).

Misalnya kita punya composite index (status, created_at, user_id):

-- ✅ BISA menggunakan index (leftmost prefix: status)
SELECT * FROM orders WHERE status = 'pending';

-- ✅ BISA menggunakan index (leftmost prefix: status, created_at)
SELECT * FROM orders WHERE status = 'pending' AND created_at > '2026-01-01';

-- ✅ BISA menggunakan index (leftmost prefix: status, created_at, user_id)
SELECT * FROM orders WHERE status = 'pending' AND created_at > '2026-01-01' AND user_id = 100;

-- ❌ TIDAK BISA menggunakan index (skip kolom pertama: status)
SELECT * FROM orders WHERE created_at > '2026-01-01';

-- ❌ TIDAK BISA menggunakan index (skip kolom pertama: status)
SELECT * FROM orders WHERE created_at > '2026-01-01' AND user_id = 100;

Bayangkan composite index seperti buku telepon yang diurutkan berdasarkan: Kota → Kecamatan → Nama. Kamu bisa mencari semua orang di “Jakarta”, atau semua orang di “Jakarta Selatan”, tapi kamu tidak bisa langsung mencari semua orang di “Kecamatan X” tanpa menyebut kota dulu.

Perbandingan: Single vs Composite Index

AspekSingle IndexComposite Index
DefinisiIndex pada 1 kolomIndex pada 2+ kolom
Query yang dilayaniFilter 1 kolom sajaFilter 1, 2, atau N kolom (sesuai leftmost prefix)
Ukuran indexKecilLebih besar (menyimpan kombinasi nilai)
Index maintenanceRinganLebih berat saat INSERT/UPDATE
Kapan pakaiQuery selalu filter 1 kolomQuery filter banyak kolom, atau ingin covering index
Covering indexSulit dicapaiMudah dicapai (semua kolom SELECT ada di index)

Covering Index: Keunggulan Tersembunyi Composite Index

Ada satu konsep penting yang sering terlewat: covering index. Covering index terjadi ketika semua kolom yang diminta oleh query sudah tersedia di dalam index, tanpa perlu melakukan “table lookup” (mengakses data di tabel utama).

Contoh: kita punya tabel orders dengan kolom id, user_id, status, total. Query ini:

SELECT status, total FROM orders WHERE user_id = 100;

Jika kita hanya punya single index pada user_id, MySQL akan:

  1. Menggunakan index user_id untuk menemukan baris yang cocok
  2. Melakukan table lookup untuk mengambil kolom status dan total

Tapi jika kita punya composite index (user_id, status, total), MySQL bisa:

  1. Menggunakan index untuk menemukan baris yang cocok
  2. Mengambil status dan total langsung dari index (tidak perlu table lookup)

Ini jauh lebih cepat karena mengurangi I/O operasi. Anda bisa melihatnya di EXPLAIN — jika kolom Extra tertulis Using index, berarti query menggunakan covering index.

Urutan Kolom dalam Composite Index

Urutan kolom dalam composite index sangat kritikal. Berikut best practices yang saya temukan:

1. Kolom equality filter di depan, range filter di belakang

-- ✅ BAIK: status (= equality) di depan, created_at (range) di belakang
CREATE INDEX idx_orders_status_created ON orders(status, created_at);

-- Query yang bisa manfaatkan index ini:
SELECT * FROM orders WHERE status = 'pending' AND created_at > '2026-01-01';

2. Kolom dengan HIGH cardinality di depan

Cardinality adalah jumlah nilai unik dalam suatu kolom. Kolom dengan cardinality tinggi (banyak nilai unik) sebaiknya diletakkan di depan karena lebih efektif mempersempit hasil pencarian.

-- email punya cardinality tinggi (setiap user berbeda)
-- status punya cardinality rendah (hanya: pending, shipped, delivered)

-- ✅ BAIK: email di depan
CREATE INDEX idx_users_email_status ON users(email, status);

-- ❌ KURANG IDEAL: status di depan (terlalu banyak baris yang status = 'active')
CREATE INDEX idx_users_status_email ON users(status, email);

3. Pertimbangkan query yang paling sering dijalankan

Urutan kolom harus disesuaikan dengan pola query yang paling sering dijalankan di aplikasi Anda. Jika query paling sering filter berdasarkan user_id lalu created_at, buat index (user_id, created_at).

Kapan pakai Single Index vs Composite Index?

SituasiRekomendasi
Query selalu filter 1 kolomSingle index
Query filter 2+ kolom dengan ANDComposite index
Query butuh covering indexComposite index (include kolom SELECT)
Query filter dengan OR antar kolom berbedaSingle index per kolom (index merge)
Tabel INSERT-heavy (write performance kritikal)Hati-hati dengan composite index besar
Ingin kurangi jumlah indexComposite index (1 index bisa gantikan beberapa single index)

Contoh Praktis

Misalnya kita punya tabel posts dengan kolom: id, author_id, category_id, status, created_at, title.

Scenario 1: Query filter satu kolom

-- Query ini hanya filter berdasarkan author_id
SELECT * FROM posts WHERE author_id = 5;

-- Single index sudah cukup
CREATE INDEX idx_posts_author ON posts(author_id);

Scenario 2: Query filter dua kolom + ORDER BY

-- Query ini filter author_id + status, lalu ORDER BY created_at
SELECT * FROM posts WHERE author_id = 5 AND status = 'published' ORDER BY created_at DESC;

-- Composite index (author_id, status, created_at)
-- - author_id & status untuk WHERE (equality)
-- - created_at untuk ORDER BY (menghindari filesort)
CREATE INDEX idx_posts_author_status_created ON posts(author_id, status, created_at);

Scenario 3: Query dengan SELECT spesifik (covering index)

-- Query ini hanya butuh title, tidak perlu SELECT *
SELECT title FROM posts WHERE author_id = 5 AND status = 'published';

-- Composite index yang "cover" semua kolom yang diakses
CREATE INDEX idx_posts_cover ON posts(author_id, status, title);

-- EXPLAIN akan tunjukkan "Using index" (covering index!)
EXPLAIN SELECT title FROM posts WHERE author_id = 5 AND status = 'published';

Kesalahan Umum yang Sering Terjadi

Berdasarkan pengalaman dan bacaan, berikut beberapa kesalahan umum yang sering dilakukan:

1. Membuat terlalu banyak single index

-- ❌ Terlalu banyak index
CREATE INDEX idx_orders_status ON orders(status);
CREATE INDEX idx_orders_user ON orders(user_id);
CREATE INDEX idx_orders_created ON orders(created_at);

-- ✅ Lebih baik: composite index yang melayani semua query
CREATE INDEX idx_orders_composite ON orders(user_id, status, created_at);

2. Urutan kolom yang salah

-- Query paling sering: WHERE status = 'pending' AND user_id = 5
-- Tapi index dibuat: (user_id, status)

-- ❌ Index kurang optimal
CREATE INDEX idx_orders_bad ON orders(user_id, status);

-- ✅ Index lebih optimal (status di depan karena equality filter)
CREATE INDEX idx_orders_good ON orders(status, user_id);

3. Tidak menggunakan EXPLAIN

Selalu gunakan EXPLAIN sebelum dan sesudah membuat index untuk memastikan index benar-benar digunakan:

EXPLAIN SELECT * FROM orders WHERE status = 'pending' AND created_at > '2026-01-01';

-- Perhatikan kolom:
-- - type: ref, range, atau eq_ref (bagus) vs ALL (full scan = buruk)
-- - key: nama index yang digunakan
-- - Extra: "Using index" = covering index (bagus sekali)

Refleksi Saya

Belajar tentang index ini membuat saya sadar: index bukan sekadar “tambah biar cepat”. Ada ilmu di balik urutan kolom, pemilihan kolom, dan pemahaman pola query. Composite index memang lebih powerful, tapi harus dipahami aturan leftmost prefix-nya. Kalau tidak, index yang sudah dibuat malah tidak terpakai.

Satu hal yang paling berkesan: EXPLAIN adalah sahabat terbaik. Sebelum optimasi, jalankan EXPLAIN dulu. Sesudah buat index, jalankan lagi. Kalau type masih ALL (full table scan), berarti index belum optimal. Semoga catatan ini bermanfaat, dan semoga saya bisa mengaplikasikan ilmu ini di proyek-proyek berikutnya.

Berita Coding & Web Dev Terbaru (17 Agustus 2026)

Kumpulan berita coding, web dev & AI paling menarik minggu ini (10-16 Agustus 2026). Dari Anthropic yang buka system prompt Claude sampai drama Cloudflare yang suntikkan analytics diam-diam — ada yang perlu kamu tahu sebagai developer.

1. Anthropic Publikasikan System Prompts Claude

Anthropic membuka sistem prompt yang digunakan di claude.ai dan aplikasi mobile Claude. Dokumentasi ini menunjukkan bagaimana prompt system mendorong perilaku Claude — mulai dari memberikan tanggal terkini, memastikan kode selalu dalam format Markdown, hingga berbagai panduan perilaku lainnya. Berguna banget buat yang mau memahami cara Anthropic membingkai interaksi model mereka.

🔗 Baca di Claude Platform Docs

2. OpenAI Ultrafast: GPT-5.6 Sol 14x Lebih Cepat

OpenAI meluncurkan mode preview “Ultrafast” untuk model terbaru mereka GPT-5.6 Sol yang membuat inference berjalan hingga 14x lebih cepat. Ini bagian dari strategi OpenAI untuk menarik pengguna enterprise yang butuh kecepatan tanpa mengorbankan kualitas respons.

🔗 Baca di TechCrunch

3. SpaceX Resmi Akuisisi Cursor

Startup AI coding Cursor resmi menjadi bagian dari SpaceX setelah proses akuisisi selesai. Cursor, yang dikenal sebagai code editor berbasis AI yang populer di kalangan developer, kini bergabung di bawah payung perusahaan Elon Musk — sebuah langkah menarik yang menggabungkan AI coding dengan aerospace.

🔗 Baca di TechCrunch

4. Cloudflare Suntikkan Analytics JavaScript Secara Diam-diam

Seorang developer menemukan bahwa Cloudflare diam-diam menyuntikkan snippet analytics JavaScript ke halaman HTML saat kamu mengganti nameserver ke Cloudflare. Temuan ini bikin heboh di HN karena banyak yang tidak menyadari bahwa ada kode tracking yang otomatis ditambahkan ke website mereka. Penting untuk diketahui developer yang concern soal privasi dan transparansi.

🔗 Diskusi di Hacker News

5. CSS Tricks: Custom Highlight API, Navigation Matching & Lainnya

Edisi #17 dari seri What’s !important di CSS-Tricks membahas beberapa fitur CSS terbaru: Custom Highlight API untuk styling selection, CSS Navigation Matching, perbaikan text-stroke, cara membuat skeleton UI, dan diagonal scrolling. Plus bagaimana gambar bisa overflow dari container sendiri. Kumpulan technique CSS yang powerful untuk daily use.

🔗 Baca di CSS-Tricks

6. Blocked aria-hidden: Fix yang Salah & Yang Benar

Artikel penting soal accessibility: peringatan aria-hidden di browser itu benar, dan sebagian besar “fix” yang beredar di internet (blur, setTimeout, menghapus attribute) sebenarnya salah — mereka hanya menutupi warning tanpa menyelesaikan masalah bagi pengguna screen reader. Kuncinya: focus harus keluar dari region sebelum region tersebut di-hide atau di-inert. Artikel ini juga merekomendasikan migrasi ke elemen <dialog> native jika memungkinkan.

🔗 Baca di CSS-Tricks

7. Software Engineering Fundamentals Matter More Than Ever

Di tengah maraknya AI coding tools, artikel ini mengingatkan bahwa fundamental software engineering justru semakin penting. Dengan AI yang bisa menghasilkan kode dalam sekejap, kemampuan untuk menulis arsitektur yang solid, memahami trade-off, dan melakukan code review yang kritis menjadi skill yang semakin berharga — bukan malah tergantikan.

🔗 Baca selengkapnya

Itu dia 7 berita paling menarik minggu ini. Yang follow perkembangan AI wajib tahu soal Claude system prompts dan OpenAI Ultrafast. Jangan lupa cek aria-hidden fix kalau lagi kerja modal dialog — accessibility itu bukan optional!

Pakai Model Non-Thinking untuk Coding Kompleks: Bisa, Asal Tahu Batasnya

Hari ini saya coba jawab pertanyaan yang sering muncul di kalangan yang baru mulai pakai AI coding agent: “Kalau pakai model non-thinking, apakah tetap bisa dipakai untuk coding yang kompleks?” Singkatnya: bisa, tapi dengan syarat — dan ada jenis pekerjaan yang memang lebih aman diserahkan ke model thinking. Catatan ini saya tulis khusus dari sudut pandang coding (Hermes Agent dan OpenCode), tidak membahas hal lain di luar itu.

Apa Bedanya Model Thinking vs Non-Thinking?

Dalam konteks coding, “thinking” (atau extended thinking / reasoning) artinya model diberi ruang untuk berpikir panjang sebelum menjawab — ia menuliskan rantai penalaran internal dulu, baru menghasilkan kode atau keputusan. Ini memakai token tambahan (biasanya tidak terlihat di output akhir), sehingga lebih lambat dan lebih mahal.

Model non-thinking menjawab langsung: input diproses, output langsung keluar. Lebih cepat, lebih murah, tapi untuk masalah yang butuh penalaran bertingkat, hasilnya bisa meleset lebih cepat.

Penting: yang wajib dimiliki untuk coding adalah kemampuan tool calling yang baik (membaca file, menjalankan perintah, melihat error, mengedit). Mode thinking itu nilai tambah, bukan prasyarat.

Kapan Non-Thinking Masih Andal

Untuk jenis pekerjaan berikut, model non-thinking yang bagus biasanya sudah cukup:

  • Boilerplate dan scaffolding — kerangka proyek, file konfigurasi, stub fungsi.
  • CRUD sederhana — endpoint API, form, operasi database standar.
  • Task satu file dengan spesifikasi eksplisit — “ubah fungsi ini supaya menerima parameter X”.
  • Refactor kecil dan mekanis — rename, pindah fungsi, ubah format.
  • Perbaikan bug yang error-nya jelas dan lokal.

Ciri umumnya: tugasnya jelas, ruang lingkupnya sempit, dan ada cara verifikasi cepat (test, compile, atau output yang bisa dicek).

Di Mana Non-Thinking Sering Gagal

Yang berikut ini justru menjadi titik lemah model non-thinking:

  • Debugging bertingkat — error menimpa error, root cause tersembunyi di balik gejala.
  • Refactor lintas file — banyak dependensi silang yang harus diikuti konsistensinya.
  • Keputusan arsitektur — memilih desain dengan trade-off yang saling bertabrakan.
  • Memahami codebase besar yang belum familiar — butuh penalaran panjang untuk membangun model mental.
  • Task ambigu — spesifikasi tidak lengkap, perlu inferensi dan pertimbangan.

Pada kasus seperti ini, model non-thinking berisiko gagal diam-diam: hasilnya terlihat jalan, tapi logikanya salah di tempat yang tidak langsung kelihatan.

Bukti dari Benchmark

Di benchmark agentic coding seperti SWE-bench Verified (500 isu GitHub nyata dari repo populer seperti Django, Flask, scikit-learn yang harus diselesaikan oleh model), posisi papan atas hampir selalu diisi model reasoning/thinking. Menurut leaderboard yang dipantau benchlm.ai per Agustus 2026, model teratas (Claude Opus 5) mencapai sekitar 96% resolusi.

Pola umumnya: versi thinking dari sebuah model hampir selalu mengungguli versi non-thinking-nya pada task multi-step, dan gap-nya mengecil drastis pada task sederhana. Jadi benchmark ini menegaskan — bukan soal “bisa atau tidak”, tapi soal di titik mana non-thinking mulai jebol.

Perbandingan Ringkas

AspekNon-ThinkingThinking
BiayaMurahMahal (token reasoning)
KecepatanCepatLambat
Konsumsi tokenHematBoros
Task sederhana & jelasSangat cocokBisa, tapi boros
Debugging & refactor besarRisiko gagal diam-diamAndal

Pola Praktis: Campur, Jangan Pilih Satu

Cara paling efektif bukan memilih salah satu, tapi memakai keduanya sesuai tugas — di Hermes dan OpenCode, ganti model per sesi/per task itu normal.

Hermes Agent

Ganti model kapan saja via hermes model, atau langsung set default:

hermes model
hermes config set model.default nama-model-non-thinking

Di dalam sesi, perintah /model untuk ganti model, dan /reasoning untuk mengatur level reasoning — kalau modelnya memang mendukung mode thinking. Model non-thinking tetap jalan normal tanpa setting tambahan.

OpenCode

Pilih model via /models. Kalau model default-nya thinking (misalnya Claude lewat provider Anthropic) dan ingin mematikannya, set lewat opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "models": {
        "claude-sonnet-4-5": {
          "options": {
            "thinking": { "type": "disabled" }
          }
        }
      }
    }
  }
}

Untuk provider OpenAI-compatible (misalnya GPT), mode reasoning diatur lewat reasoningEffort — nilai rendah berarti “hampir non-thinking”.

Kesimpulan

Model non-thinking bisa dipakai untuk coding kompleks, asal tugas dipecah kecil dan ada loop verifikasi: tulis sedikit → jalankan → lihat error → perbaiki. Untuk boilerplate, CRUD, dan task single-file, non-thinking bahkan pilihan paling efisien.

Tapi untuk debugging bertingkat, refactor lintas file, dan keputusan desain, model thinking masih pilihan yang jauh lebih aman — terutama kalau pekerjaan berjalan tanpa pengawasan. Prinsipnya: pakai model sesuai tingkat kesulitan tugas, bukan satu model untuk segalanya.

Sumber