Index with Sort #
Dalam praktik sehari-hari, banyak query database yang terlihat sederhana tapi diam-diam mahal biayanya. Salah satu penyebab paling umum adalah proses sorting (ORDER BY). Sorting sering dianggap “gratis”, padahal di balik layar database bisa melakukan operasi yang sangat berat: full scan, in-memory sort, atau bahkan disk-based sort.
Di sinilah index dengan aspek sort (ordered index) menjadi sangat krusial. Artikel ini membahas:
- Apa itu sorting di index
- Kapan index bisa (dan tidak bisa) membantu
ORDER BY - Bagaimana database memanfaatkan index untuk sorting
- Best practice desain index terkait sorting
Artikel ini fokus pada konsep dan best practice, bukan spesifik vendor, meskipun contoh logikanya relevan untuk MySQL, PostgreSQL, dan database relasional modern.
Apa Itu Sorting di Index? #
Secara fundamental, index database selalu tersimpan dalam keadaan terurut.
Contoh sederhana:
CREATE INDEX idx_users_created_at ON users(created_at);
Index di atas secara fisik tersimpan dalam struktur seperti B-Tree, di mana created_at sudah sorted ascending.
Artinya:
- Database tidak perlu melakukan sort ulang
- Engine cukup melakukan index scan dari awal ke akhir (atau sebaliknya)
Inilah yang disebut sebagai index-assisted sorting.
Masalah Besar: Sorting Tanpa Index #
Pertimbangkan query berikut:
SELECT * FROM orders
WHERE status = 'PAID'
ORDER BY created_at DESC
LIMIT 20;
Jika tidak ada index yang mendukung created_at:
- Database membaca semua row dengan
status = 'PAID' - Menyimpan hasilnya di memory (atau disk jika besar)
- Melakukan sorting
- Baru mengambil 20 data teratas
Konsekuensi:
- CPU tinggi
- Memory pressure
- Disk temporary table
- Latency tidak linear (data sedikit cepat, data besar mendadak lambat)
⚠️ LIMIT tidak menyelamatkan query tanpa index sort
Kapan Sorting di Index Dibutuhkan? #
Query dengan ORDER BY yang Sering Dipakai #
Jika sebuah endpoint selalu memanggil data terurut, maka index sort hampir selalu dibutuhkan.
Contoh umum:
- Timeline (
ORDER BY created_at DESC) - Log aktivitas
- Riwayat transaksi
- Data admin panel (latest first)
Query dengan LIMIT Kecil Tapi Data Besar #
Contoh klasik:
SELECT * FROM logs
ORDER BY created_at DESC
LIMIT 10;
Tanpa index:
- Tetap scan seluruh table
Dengan index:
- Database cukup membaca 10 entry pertama dari index
Perbedaan kompleksitas:
- Tanpa index: O(n log n)
- Dengan index: O(log n + k)
Sorting Setelah Filtering (Composite Index) #
Sorting hampir selalu datang bersamaan dengan WHERE.
Contoh:
SELECT * FROM orders
WHERE user_id = 42
ORDER BY created_at DESC
LIMIT 20;
Index ideal:
CREATE INDEX idx_orders_user_created
ON orders(user_id, created_at DESC);
Kenapa?
- Database bisa filter
user_iddulu - Data hasil filter sudah terurut
- Tidak ada sort tambahan
Composite Index dan Sorting #
Urutan Kolom Sangat Penting #
Index berikut:
(user_id, created_at)
✔️ Optimal untuk:
WHERE user_id = ? ORDER BY created_at
❌ Tidak optimal untuk:
WHERE created_at > ? ORDER BY user_id
Rule penting: sorting hanya efektif jika kolom
ORDER BYberada setelah kolom equality (=) di index
Arah Sorting (ASC / DESC) #
Sebagian besar database modern:
- Bisa scan index maju atau mundur
- Tidak selalu butuh index terpisah untuk ASC dan DESC
Namun:
- Composite index dengan mixed order tetap harus hati-hati
Contoh:
(user_id ASC, created_at DESC)
Gunakan hanya jika:
- Query sangat konsisten
- Arah sorting benar-benar fixed
Covering Index dan Sorting #
Index menjadi jauh lebih powerful jika:
- Semua kolom SELECT ada di index
Contoh:
SELECT id, created_at
FROM orders
WHERE user_id = ?
ORDER BY created_at DESC
LIMIT 10;
Index:
(user_id, created_at, id)
Manfaat:
- Tidak perlu lookup ke table
- Zero random I/O
- Latency sangat rendah
Ini sering disebut:
- Covering index
- Index-only scan
Kapan Index Sorting Tidak Berguna? #
ORDER BY dengan Function #
ORDER BY DATE(created_at)
❌ Index tidak bisa dipakai
Solusi:
- Simpan kolom ter-derivasi
- Atau gunakan generated column
ORDER BY Kolom yang Tidak Selektif #
Contoh:
ORDER BY status
Jika status hanya punya 3 nilai:
- Index jarang membantu
- Sorting cost tetap tinggi
ORDER BY Random #
ORDER BY RAND()
❌ Tidak bisa dioptimasi dengan index
Best Practice Desain Index untuk Sorting #
Selalu Analisis Query Nyata #
Bukan teori.
- Lihat query paling sering dipanggil
- Perhatikan
ORDER BY + LIMIT
Gabungkan Filter + Sort dalam Satu Index #
WHERE A = ? AND B = ? ORDER BY C
Index:
(A, B, C)
Jangan Membuat Index Hanya Karena ORDER BY #
Index punya biaya:
- Write lebih lambat
- Storage bertambah
Buat index hanya jika:
- Query dipanggil sering
- Latency penting
Gunakan EXPLAIN, Bukan Perasaan #
Pastikan:
Using index- Tidak ada
Using filesort
Ringkasan Mental Model #
| Kondisi Query | Index Sorting Efektif? |
|---|---|
| ORDER BY + LIMIT | ✅ Sangat |
| WHERE + ORDER BY | ✅ Jika composite index benar |
| ORDER BY function | ❌ |
| ORDER BY random | ❌ |
| Data kecil | ❓ Tidak signifikan |
Penutup #
Sorting bukan sekadar urusan tampilan data, tapi salah satu faktor performa paling mahal di database.
Index yang dirancang dengan benar bisa mengubah:
- Query 5–8 detik
- Menjadi < 50 ms
Namun index yang salah justru:
- Membebani write
- Memboroskan storage
- Tidak pernah dipakai
Desain index untuk sorting bukan soal teori, tapi membaca pola akses data.