Kamu lagi semangat nambahin fitur search di aplikasi, tapi begitu query-nya mulai join ke banyak tabel dan pakai LIKE '%keyword%', performanya langsung anjlok. Data baru ribuan aja udah 700 ms—gimana kalau nanti jutaan? Insting pertama mungkin langsung mikir: “Udah, pakai Elasticsearch aja.” Tapi tunggu dulu. Di sinilah banyak developer terjebak over-engineering. Saya akan tunjukkan kenapa full-text search bawaan database kamu justru bisa jadi solusi paling elegan, tanpa tambahan infrastruktur, dan dengan perubahan kode yang minimal.
Kenapa LIKE Query Bisa Jadi Bom Waktu
Masalah utama dari LIKE dengan leading wildcard (%keyword%) adalah dia memaksa full table scan. Database membaca setiap baris dari awal sampai akhir tanpa bisa memanfaatkan indeks biasa. Kalau cuma satu tabel kecil dan traffic rendah, ini masih aman-aman saja. Begitu data menumpuk dan request masuk ribuan, bottleneck langsung terasa.
Di kasus yang kita bahas, si penanya harus join ke 10 tabel, dua di antaranya bahkan polymorphic (tanpa relasi langsung), dan pencarian dilakukan ke banyak kolom sekaligus. Mau seberapa kencang server-mu, kombinasi JOIN banyak + LIKE + data gede pasti bikin query meringis.
Kabar baiknya: kamu nggak harus langsung lompat ke NoSQL. Ada peta jalan tiga tahap yang bisa kamu tempuh secara bertahap, dimulai dari yang paling sederhana dulu.
Tahap 1: Denormalisasi – Gabung Tabel yang Bisa Disatukan
Di kuliah kita diajari normalisasi bentuk ketiga biar tabel-tabel rapi. Tapi di dunia nyata, performa sering jadi prioritas utama. Kalau kamu punya relasi one-to-one yang jarang berubah, gabungin aja dulu jadi satu tabel.
Contoh:
Daripada products join ke brands, categories, dan sellers hanya untuk nyari data di kolom nama, kamu bisa taruh brand_name, category_name langsung di tabel products. Kolom ini di-update via trigger atau event di aplikasi agar tetap sinkron.
Kapan cocok:
- Relasi hasil join relatif statis (nama brand jarang ganti).
- Jumlah data masih ratusan ribu, belum jutaan.
- Ingin mengurangi jumlah JOIN tanpa merombak arsitektur kode.
Kalau setelah denormalisasi query masih lambat karena volume data besar dan pencarian tetap butuh menyisir teks, lanjut ke tahap berikutnya.
Tahap 2: CQRS Sederhana dengan Tabel Pencarian Khusus
Ini trik yang sering saya rekomendasikan. CQRS (Command Query Responsibility Segregation) tidak harus serumit event sourcing. Untuk keperluan search, kamu cukup membuat satu tabel flat yang khusus dipakai buat pencarian.
Caranya:
- Buat tabel baru, misalnya
product_search. - Isi dengan kolom-kolom yang ingin kamu cari:
product_name,brand_name,category_name,seller_name, dsb. - Setiap ada perubahan di tabel induk (insert/update/delete), sinkronkan juga ke
product_search– bisa lewat trigger, queue, atau langsung di service layer.
Sekarang query pencarianmu cukup menyerang satu tabel saja, tanpa JOIN bertele-tele. Memang masih mungkin kamu pakai LIKE di sini, tapi karena beban JOIN hilang, performa jauh lebih baik. Idealnya, kini saatnya kamu resmi upgrade ke mesin pencarian sungguhan.
Tahap 3: Full-Text Search – Kekuatan Tersembunyi di MySQL/PostgreSQL
Inilah jurus pamungkas yang nggak banyak dipakai, padahal ada di depan mata. Baik MySQL (min. 5.6 InnoDB) maupun PostgreSQL punya fitur full-text search yang bisa mencari satu kata ke beberapa kolom sekaligus, jauh lebih cepat dari LIKE. Kamu tinggal bikin full-text index yang mencakup kolom-kolom yang diinginkan, lalu gunakan fungsi MATCH ... AGAINST (MySQL) atau tsvector (PostgreSQL).
Simulasinya di MySQL:
- Buat indeks pada tabel
product_search:
ALTER TABLE product_search ADD FULLTEXT(product_name, brand_name, category_name, seller_name);
- Query-nya jadi:
SELECT * FROM product_search
WHERE MATCH(product_name, brand_name, category_name, seller_name)
AGAINST('Apple' IN NATURAL LANGUAGE MODE);
Kenapa ini menguntungkan?
- Bukan full table scan – indeks full-text bekerja dengan menyimpan daftar kata dan frekuensinya, pencarian langsung menuju kata yang cocok.
- Satu indeks melayani banyak kolom, cocok buat kebutuhan “cari satu kata di mana saja”.
- Tanpa tambahan database – tetap pakai instance yang sama, tanpa investasi hardware baru.
Selama fitur search kamu masih wajar (tanpa sinonim, koreksi ejaan, atau similarity berbobot), full-text search bawaan sudah lebih dari cukup untuk jutaan data sekalipun.
Kapan Kamu Baru Perlu NoSQL?
Gunakan Elasticsearch, Solr, atau Meilisearch hanya jika kebutuhan pencarianmu sudah seperti Google mini:
- Harus menangani salah ketik (typo tolerance) dan kata dengan bunyi mirip (fuzzy search).
- Butuh sinonim dan stemming untuk berbagai bahasa.
- Ingin scoring yang rumit berdasarkan relevansi kontekstual.
Kalau cuma “cari kata di kolom nama produk, brand, kategori” tanpa fitur tadi, mengadopsi NoSQL terlalu dini adalah over-engineering yang bengkak di biaya dan kompleksitas. Ingat, kamu harus maintain sinkronisasi data, menambah operasional server baru, dan mengubah paradigma kode dari SQL ke query DSL. Biaya overhead-nya bisa jauh lebih besar daripada manfaatnya di fase awal.
Strategi Penerapan Berdasarkan Skala Data & Traffic
Untuk memudahkan kamu memilih, ini ringkasan jalurnya:
- Data kecil (ribuan), traffic rendah →
LIKEjoin banyak tabel masih oke. Pantau, baru optimasi saat terasa lambat. - Data menengah, join mulai berat → Denormalisasi untuk kurangi join, atau langsung terapkan CQRS dengan tabel flat.
- Data besar (>ratusan ribu), perlu cari teks ke banyak kolom → Full-text search index di tabel flat. Ini titik manis performa tanpa tambahan ekosistem.
- Butuh pencarian super canggih (typo, similarity) → Baru pertimbangkan NoSQL.
Dengan bertahap seperti ini, kamu tetap waras, product owner puas karena performa oke, dan infrastruktur nggak jebol biaya.
Yuk, bagikan pengalamanmu! Kalau kamu pernah berurusan dengan query LIKE yang bikin server nangis, taktik apa yang akhirnya kamu pakai? Tulis di kolom komentar—siapa tahu jadi solusi buat teman-teman lain. Dan kalau kamu merasa artikel ini menyelamatkan sprint-mu minggu ini, jangan lupa subscribe channel ini biar kamu dapat update tips-tips database yang praktis dan nggak textbook banget.
Yang Sering Ditanyakan (FAQ)
Tidak selalu, dan ini tergantung kebutuhan. Full-text search unggul untuk pencarian berbasis kata alami, misalnya mencari “Apple” di kolom nama produk, brand, atau kategori sekaligus. Ia memanfaatkan indeks khusus sehingga jauh lebih cepat dari LIKE '%kata%' yang melakukan full table scan. Namun, jika kamu butuh pencarian pola wildcard yang sangat spesifik (misal LIKE 'AP%LE') atau pencocokan persis di tengah string, LIKE tetap lebih fleksibel. Intinya: untuk fitur search box ala toko online atau blog, full-text search adalah pengganti yang nyaris sempurna.
Saat kebutuhan pencarianmu sudah menyentuh fitur-fitur “Google mini”: toleransi salah ketik (typo tolerance), pencarian dengan bunyi mirip (fuzzy search), sinonim, stemming multi-bahasa, atau skoring relevansi yang rumit. Jika aplikasi kamu hanya butuh mencari satu kata di beberapa kolom—tanpa koreksi otomatis atau rekomendasi berbobot—full-text search bawaan MySQL/PostgreSQL sudah sangat memadai dan jauh lebih hemat dari sisi biaya operasional.
Sangat sanggup. Indeks FULLTEXT di InnoDB (MySQL 5.6+) dan tsvector di PostgreSQL dirancang untuk pencarian teks skala besar. Ia menyimpan token kata dan frekuensinya, sehingga pencarian langsung menuju kata yang cocok tanpa menyisir seluruh baris. Untuk puluhan juta data, selama indeks terkelola dengan baik dan query tidak melakukan join liar, performanya tetap tinggi. Kalau performa mulai menurun, kamu bisa mempertimbangkan partisi tabel atau materialized view—itu pun masih tetap satu database, tanpa tambahan server.



