6 poin oleh GN⁺ 2023-07-13 | 1 komentar | Bagikan ke WhatsApp
  • Pencarian teks lengkap PostgreSQL adalah pendekatan untuk membangun fitur pencarian tanpa mesin pencari terpisah dengan menggabungkan tsvector, tsquery, @@, ts_rank, dan indeks GIN
  • Kata kunci dan dokumen dinormalisasi pada tingkat lexeme, dan kueri dapat diekspresikan dengan operator seperti AND, OR, NOT, dan FOLLOWED BY sehingga sebagian besar sintaks pencarian umum bisa diimplementasikan
  • Dalam lingkungan contoh, indeks GIN mengurangi waktu pencarian dari lebih dari 200ms menjadi sekitar 4ms, tetapi ketika hasil sangat banyak, biaya pemeringkatan dan pengurutan ts_rank dapat menjadi bottleneck
  • Penyesuaian relevansi dapat diimplementasikan dengan menambahkan sinyal seperti bobot judul, jumlah suara, rating, genre, dan kebaruan ke dalam ekspresi pengurutan, atau dengan memberi bobot kolom melalui setweight
  • Toleransi typo, pencarian facet, autocomplete, pencarian frasa yang presisi, dan pencarian hibrida juga dimungkinkan, tetapi di PostgreSQL komponen-komponennya harus dirangkai sendiri dan batas performa pada dataset besar perlu diuji

Pendekatan PostgreSQL untuk pencarian teks lengkap

  • PostgreSQL menyediakan komponen tingkat rendah untuk pencarian teks lengkap, yang dapat digabungkan untuk membangun fitur mesin pencari
  • Pendekatan ini fleksibel, tetapi membutuhkan lebih banyak pekerjaan implementasi dibanding Elasticsearch, Typesense, atau Meilisearch yang memang berfokus pada pencarian teks lengkap
  • Kueri contoh menggunakan dataset Kaggle Wikipedia Movie Plots
    • Berisi 34.000 judul film
    • Ukuran dalam format CSV sekitar 81MB

Komponen inti

  • Pencarian teks lengkap PostgreSQL bekerja dengan elemen-elemen berikut
    • tsvector: menyimpan teks yang akan dicari sebagai daftar lexeme yang telah dinormalisasi
    • tsquery: merepresentasikan kueri pencarian yang telah dinormalisasi
    • @@: operator pencocokan untuk memeriksa apakah tsquery cocok dengan tsvector
    • ts_rank, ts_rank_cd: menghitung skor relevansi hasil pencarian
    • Indeks GIN: indeks terbalik untuk mengkueri tsvector secara efisien

tsvector dan konfigurasi pencarian

  • tsvector menyimpan daftar lexeme yang telah diurutkan
    • Lexeme mirip token, tetapi merupakan string yang telah dinormalisasi agar berbagai bentuk kata yang sama disatukan
    • Dalam konfigurasi bahasa Inggris, normalisasi dilakukan dengan mengubah huruf besar menjadi kecil dan menghapus sufiks
  • Saat kalimat bahasa Inggris diurai dengan to_tsvector, stop word seperti “I”, “to”, dan “an” dihapus
    • “refuse” dan “Refusing” sama-sama diubah menjadi refus
    • Tanda baca diabaikan
    • Posisi kata dan bobotnya dalam teks asli juga dicatat
  • Jika menggunakan konfigurasi simple alih-alih english, kata disertakan sesuai bentuk yang ditemukan di teks
    • “refuse” dan “refusing” tetap menjadi lexeme yang berbeda
    • Konfigurasi simple sangat berguna terutama untuk kolom yang berisi label atau tag
  • PostgreSQL menyediakan konfigurasi pencarian bawaan untuk banyak bahasa, tetapi tidak untuk CJK (Tionghoa, Jepang, Korea)
    • Untuk bahasa yang tidak didukung, konfigurasi simple bisa bekerja cukup praktis
    • Namun, belum pasti apakah ini cukup untuk CJK

tsquery dan ekspresi kueri

  • tsquery adalah tipe data untuk merepresentasikan kueri pencarian yang telah dinormalisasi
    • Kata pencarian harus sudah berupa lexeme yang dinormalisasi
    • Beberapa istilah pencarian dapat digabungkan dengan operator AND, OR, NOT, dan FOLLOWED BY
  • to_tsquery, plainto_tsquery, dan websearch_to_tsquery membantu mengubah teks masukan pengguna menjadi tsquery yang sesuai
    • Peran utamanya adalah menormalisasi kata-kata dalam teks masukan
  • Dengan websearch_to_tsquery, kueri bisa dibuat lebih mirip kotak pencarian umum
    • darth vader diperlakukan sebagai AND logis yang mengharuskan kedua kata ada dalam dokumen
    • Pencarian OR dan pengecualian kata juga dimungkinkan
    • Pencarian frasa mengekspresikan bentuk ketika kata-kata muncul berurutan
  • Dalam konfigurasi bahasa Inggris, stop word seperti “the” dihapus sehingga pada beberapa pencarian frasa hampir seluruh frasa bisa hilang
    • Dalam kasus seperti ini, penggunaan konfigurasi simple dapat memberi hasil yang sesuai harapan
  • Operator @@ digunakan untuk memeriksa apakah tsquery cocok dengan tsvector

Indeks GIN dan performa pencarian

  • GIN adalah singkatan dari Generalized Inverted Index, yaitu tipe indeks yang dirancang untuk kueri yang mencari nilai elemen di dalam nilai majemuk
  • GIN dapat digunakan bukan hanya untuk pencarian teks tetapi juga kueri JSON
  • Anda dapat membuat kolom tsvector yang menggabungkan beberapa kolom yang dapat dicari, lalu membuat indeks GIN pada kolom tersebut
  • Dalam lingkungan contoh, indeks GIN mengurangi waktu pencarian dari lebih dari 200ms menjadi sekitar 4ms

Pemeringkatan dan perhitungan relevansi

  • Untuk pengalaman pencarian yang baik, hasil harus diurutkan berdasarkan relevansi
  • PostgreSQL menyediakan dua fungsi pemeringkatan bawaan: ts_rank dan ts_rank_cd
    • Keduanya mempertimbangkan frekuensi kemunculan istilah pencarian
    • ts_rank_cd juga mencerminkan kedekatan antar lexeme yang cocok
  • Relevansi sangat bergantung pada karakter aplikasi
    • Fungsi pemeringkatan bawaan lebih merupakan titik awal, dan bila perlu dapat dibuat fungsi pemeringkatan sendiri atau digabungkan dengan faktor lain
  • ts_rank perlu mengakses kolom search dari setiap hasil
    • Jika banyak baris cocok dengan kondisi WHERE, PostgreSQL harus mengunjungi semuanya untuk menghitung ranking dan melakukan pengurutan
    • Dalam lingkungan contoh, satu kueri dikembalikan dalam 5–7ms, tetapi kueri seperti darth OR vader yang perlu memberi peringkat pada lebih dari 1.000 hasil memerlukan sekitar 80ms

Tuning relevansi

  • Relevansi berbasis frekuensi kata adalah default yang baik, tetapi data bisa memiliki sinyal yang lebih penting daripada frekuensi
  • Dalam dataset film, sinyal-sinyal berikut dapat dimasukkan ke relevansi
    • Hasil yang cocok di judul dianggap lebih penting daripada hasil yang cocok di deskripsi atau plot
    • Film yang lebih populer dapat dinaikkan berdasarkan rating atau jumlah suara
    • Jika pengguna menyukai komedi, film komedi bisa ditempatkan lebih tinggi
    • Judul yang lebih baru dapat dianggap lebih relevan daripada judul lama
  • Mesin pencari khusus menyediakan fitur untuk mengatur bagaimana kolom atau field yang berbeda memengaruhi ranking

Boosting berbasis angka, tanggal, dan nilai yang presisi

  • PostgreSQL tidak menyediakan boosting berbasis kolom lain secara langsung, tetapi ranking pada akhirnya hanyalah ekspresi pengurutan, sehingga sinyal kustom bisa ditambahkan
  • Untuk mencerminkan jumlah suara, ini bisa diimplementasikan dengan menambahkan boost berbasis jumlah suara ke skor ranking
    • Contoh menggunakan log agar pengaruhnya lebih landai
    • Koefisien 0.01 digunakan agar booster berada pada skala yang mirip dengan skor ranking
  • Fungsi yang lebih kompleks juga bisa dibuat, misalnya untuk menaikkan rating hanya ketika jumlah suara melewati ambang tertentu
  • Jika ingin menaikkan genre tertentu, fungsi seperti valueBooster yang mengembalikan koefisien hanya saat nilainya cocok dengan nilai kolom tertentu dapat digunakan

Bobot kolom

  • Lexeme dalam tsvector dapat diberi bobot
  • PostgreSQL mendukung empat bobot: A, B, C, dan D
    • A adalah bobot tertinggi
    • D adalah bobot terendah dan nilai default
  • Fungsi setweight dapat digunakan untuk mengontrol bobot saat membuat kolom tsvector
  • Jika kolom judul diberi bobot lebih tinggi, film yang kata kuncinya muncul di judul akan naik ke bagian atas hasil dan skor rankingnya juga meningkat
  • Fakta bahwa hanya ada empat kelas bobot merupakan keterbatasan, dan bobot harus diterapkan saat tsvector dihitung

Toleransi typo dan pencarian fuzzy

  • PostgreSQL tidak secara langsung mendukung pencarian fuzzy atau toleransi typo saat menggunakan tsvector dan tsquery
  • Dengan asumsi typo ada di sisi kueri, ini dapat diimplementasikan dengan cara berikut
    • Mengindeks semua lexeme dari konten ke tabel terpisah
    • Untuk setiap kata dalam kueri, mencari kandidat kata dengan similarity atau Levenshtein distance
    • Merevisi kueri agar mencakup kata-kata yang ditemukan
    • Menjalankan pencarian dengan kueri yang telah direvisi
  • Contoh menggunakan Levenshtein distance karena itulah pendekatan yang dipakai mesin pencari untuk pencarian fuzzy
  • Setelah daftar kandidat kata diperoleh, kueri perlu disesuaikan agar mencakup semua kata tersebut

Pencarian facet

  • Pencarian facet banyak digunakan terutama di situs e-commerce agar pengguna dapat mempersempit cakupan pencarian secara bertahap
  • Di PostgreSQL, ini dapat diimplementasikan dengan mendefinisikan kategori secara manual lalu menambahkannya ke kondisi WHERE pencarian
  • Dimungkinkan juga membuat kategori secara algoritmis berdasarkan data yang ada
    • Dalam contoh, facet “Decade” dibuat berdasarkan tahun film
    • Jumlah kecocokan per decade juga bisa dihitung dan ditampilkan dalam tanda kurung
  • Untuk mengambil beberapa facet dalam satu kueri, CTE dapat digabungkan
  • Pendekatan ini dapat bekerja baik untuk dataset kecil hingga menengah, tetapi pada dataset yang sangat besar bisa menjadi lambat

Cakupan dan batasan mesin pencari PostgreSQL

  • Dengan menggabungkan komponen pencarian teks lengkap PostgreSQL, kita bisa membangun mesin pencari yang cukup canggih
  • Pencarian berbasis PostgreSQL juga mendukung join dan transaksi ACID
    • Ini adalah kemampuan yang umumnya tidak dimiliki mesin pencari lain
  • Topik pencarian lanjutan lain yang layak dibahas antara lain
    • Saran kata dan autocomplete
    • Pencocokan frasa yang presisi
    • Pencarian hibrida yang digabungkan dengan pg-vector
  • Fitur-fitur ini memang mungkin di PostgreSQL, tetapi komponennya harus digabungkan sendiri
  • Dalam beberapa kasus, performa dapat menurun pada dataset yang sangat besar
  • Tulisan lanjutan bagian 2 membandingkan implementasi pencarian di PostgreSQL dengan menambahkan Elasticsearch ke infrastruktur dan menyinkronkan data

1 komentar

 
GN⁺ 2023-07-13
Komentar Hacker News
  • Jangan mencoba melakukan ini dengan meniru fitur Elasticsearch
    Pada tahun 2000-an saya pernah membuat mesin pencari dengan MySQL 3.x yang mem-parsing data EXIF gambar lalu mengindeks taksonomi 3 tingkat beserta hitungannya; itu adalah sesuatu yang bahkan banyak vendor mahal pun gagal lakukan dengan benar, dan Autonomy bahkan tidak bisa menangani klasifikasi tingkat teratas
    Saya akhirnya berhasil setelah 6 minggu menulis SQL rapuh yang performanya berubah hanya karena urutan kolom SELECT diubah, tetapi saya tidak ingin melakukannya lagi. Basis data pada dasarnya masih mirip, tetapi mesin pencari sudah berkembang jauh lebih pesat
    Sebagai rasa ingin tahu intelektual, ini bisa dicoba, tetapi pencarian bukan sekadar tokenisasi lalu selesai. Segera akan muncul kebutuhan seperti penelusuran klasifikasi, multibahasa, sinonim otomatis, saran ejaan "Did you mean", performa skala besar, dan pada akhirnya Anda akan menjebak diri sendiri di jalan buntu. Demi kesehatan mental, lebih baik pakai mesin pencari, dan untuk sinkronisasi PG dengan ES juga ada alat seperti ZomboDB atau PGSync

    • Ada dua pembahasan berbeda yang tercampur di thread ini. Jika Anda membuat mesin pencari yang berhadapan dengan pelanggan, memang benar sebaiknya gunakan alat kuat seperti Elasticsearch agar tidak menciptakan ulang roda
      Sebaliknya, jika analis data atau pengembang ingin mencari kolom teks di basis data besar dengan cara yang lebih fleksibel daripada LIKE/ILIKE, mungkin lebih mudah dan cepat untuk mencapai 90% kebutuhan dengan membuat indeks/tabel full-text search di dalam basis data yang sama
  • Saya menantikan bagian 2 yang membandingkan Postgres vs Elasticsearch. Salah satu aplikasi di perusahaan menggunakan PG untuk CRUD objek dan Elastic untuk pencarian, tetapi kami benar-benar meremehkan upaya sinkronisasi dua penyimpanan data itu, dan sekarang kami sedang mempertimbangkan untuk menghapus Elasticsearch

    • Cara yang dulu saya pakai adalah memperlakukan Elasticsearch sebagai sesuatu yang selalu bisa dibangun ulang
      Setiap 5 menit sebuah cron mencari objek yang perlu diindeks di DB dengan last_modified_at > last_indexing_started_timestamp, mengindeksnya ke Elasticsearch, lalu memperbarui last_indexing_started_timestamp ke waktu dimulainya sinkronisasi. Dengan begitu, objek yang diubah antara awal dan akhir eksekusi akan tertangkap pada putaran berikutnya
      Jika Elasticsearch perlu dibangun ulang, cukup kosongkan waktu pengindeksan terakhir dan sinkronkan ulang dari awal; sistem jadi bisa memulihkan diri sendiri dan sinkronisasi tidak akan melenceng
    • Di tempat kerja sebelumnya kami memakai susunan serupa dan tidak terlalu sulit. Setiap kali entitas di PG diperbarui, kami mengirim pesan untuk direplikasi secara asinkron ke ES, dan sisi ES mengisinya dengan mengambil data dari PG berdasarkan ID
      Seperti pekerjaan asinkron pada umumnya, monitoring dan retry tetap diperlukan, tetapi ES stabil dan cepat sehingga masalah jarang terjadi. Namun kebutuhan konsistensinya cukup longgar sehingga cukup jika status terbaru PG sampai ke ES dalam waktu yang wajar; kalau kebutuhannya berbeda, hasilnya bisa berbeda juga
    • Kami juga menempuh pola serupa: Postgres untuk CRUD, Elastic untuk pencarian, lalu meremehkan bukan hanya sinkronisasi dua penyimpanan tetapi juga operasi klaster Elastic yang stabil dengan personel dan pengalaman yang terbatas
      Setelah beralih ke full-text search Postgres dengan bobot pada indeks dan kueri, kami bisa menangani semua yang dibutuhkan sepenuhnya di dalam Postgres hanya dengan trigger pembaruan dan kueri pencarian yang sangat cepat
    • Penasaran apakah ada yang pernah memakai zombodb [https://www.zombodb.com/]
    • Saya pernah, dan itu pekerjaan yang sulit bahkan dengan pengalaman yang cukup, serta beberapa hasilnya justru lebih buruk. Sebagian besar hasilnya mirip, dan hanya sebagian kecil yang lebih baik
      Secara keseluruhan itu sukses dan sangat mengurangi beban operasional sehingga waktu rekayasa yang dikeluarkan terbayar, tetapi ini bukan sesuatu untuk dimulai dengan santai
      Tergantung kebutuhan, materialized view, view biasa, dan trigger bisa jadi lebih baik. Bisa juga full-text search bawaan tidak cocok untuk use case Anda, dan membuat alternatifnya belum tentu sesulit itu
  • Tanpa waktu lookup p50/p99 pada beban yang realistis, sulit menganggap ini sudah terbukti. Mesin pencari yang mengembalikan hasil dalam 1 menit bukanlah sesuatu yang "canggih", dan basis data relasional seperti Postgres pun tentu bisa melakukannya di atas kertas

    • Sebagai penulis, saya memang berencana membuat tulisan lanjutan yang membandingkannya dengan Elasticsearch, tetapi tampaknya saya tidak akan mencoba benchmark. Skenario realistis apa pun yang saya buat belum tentu cocok dengan use case masing-masing
      Saya pada dasarnya setuju, dan pada skala besar, misalnya beberapa juta record atau lebih, kemungkinan saya tidak akan memakai pendekatan ini. Minat utama saya adalah melihat sejauh mana fungsinya bisa direplikasi
      Untuk use case pencarian kecil, ada keuntungan seperti infrastruktur yang lebih sedikit untuk dipelihara, konsistensi kuat, dan join. Di Xata, kami juga memikirkan transisi mulus dari Postgres pada skala kecil ke Elasticsearch dengan perubahan yang seminimal mungkin merusak
    • Saat saya wawancara dengan mantan karyawan Google, saya mendengar bahwa mereka menyimpan cache semua hasil untuk kueri yang pernah dilihat sebelumnya dan ikut memperbarui hasil yang di-cache saat indeks diperbarui
      Dari sudut pandang itu, hasil pencarian yang cepat sendiri tidak terlalu mengejutkan. Karena hasil cache bisa terus diperbarui lewat pekerjaan latar belakang lalu langsung disajikan saat ada permintaan. Caching dan waktu respons seperti ini tampaknya terpisah dari kecepatan perhitungan hasil pencarian yang sebenarnya
    • Ada masalah saat meminta p50/p99 pada beban realistis. Ketika banyak orang sebenarnya tidak melakukan pencarian, bagaimana kita membuat beban realistis yang benar-benar nyata untuk mesin pencari? Menghantamnya dengan kueri acak tidak realistis
      Ada pengguna dengan koneksi lambat, dan kata kunci tertentu seperti gempa bumi bisa melonjak hanya di wilayah tertentu
      Jika kueri terlalu acak, cache tidak akan punya hasil sehingga terlihat lebih buruk dari kenyataan; jika tidak cukup acak, hasilnya akan terlihat lebih baik dari kenyataan
    • Lucene, yaitu fondasi yang dipakai Elasticsearch dan Solr, menggunakan inverted index, dan GIN dalam tulisan ini juga memakai pendekatan yang sama
      Karena itu, keunggulan ES dan sejenisnya ada pada penskalaan horizontal lintas banyak node atau fitur tambahan yang diletakkan di atas indeks utama
    • Saya memakai full-text search Postgres dan itu bekerja dengan baik. Hanya saja Anda perlu tahu bagaimana memberi peringkat pada baris dalam kueri
      ts_rank saja sudah bagus, tetapi biasanya Anda ingin menyesuaikan peringkat dengan metrik relevansi lain. Jika Anda bisa menyelesaikan masalah bahwa metrik itu tidak dapat dijadikan dasar peringkat utama, hasilnya secepat kueri tabel DB biasa yang memiliki indeks
  • Saat remaja, saya pernah mencoba membuat mesin pencari dan basis data dari nol meski belum begitu paham keduanya. Saya ingin melihat seberapa jauh itu bisa dibawa, dan seberapa cepat serta seberapa relevan hasil pencarian yang bisa dikembalikan
    Membuat basis data dasar dan mesin pencari sederhana dengan cepat mungkin cukup mudah bahkan bagi programmer amatir. Jika memahami algoritme dasar ilmu komputer serta cara memanfaatkan sistem operasi dan perangkat keras, itu bisa dibuat dalam satu atau dua bulan
    Bahkan dengan bahasa tingkat tinggi, kecepatannya tidak buruk, sekitar 250 ribu QPS di laptop tahun 2003. Jika di-shard, skalabilitas juga bukan masalah besar. Yang lebih rumit daripada penyimpanan dan pengambilan adalah pengindeksan, locking, dan konsistensi
    Masalah yang benar-benar besar adalah subjektivitas pencarian. Saat pertanyaannya menjadi apa yang sebenarnya ingin dicari, bagaimana mencari ketika kita sendiri tidak tahu apa yang dicari, bagaimana mencegah orang menyalahgunakan sistem, dan bagaimana menangani kueri serta dataset yang kompleks, tingkat kesulitannya naik beberapa orde besaran

    • 250 ribu RPS tampak sangat besar, karena SQLite pun saat ini mungkin tidak bisa mencapai angka itu. Inverted index tampaknya akan lebih mahal, dan RocksDB juga sekitar 130 ribu RPS; perangkat keras untuk angka itu mungkin lebih kuat daripada laptop saya atau lingkungan saya yang keliru
      Saya penasaran apakah benar menggunakan basis data serbaguna dan apakah angka itu akurat. Saya ingin tahu teknik apa yang dipakai untuk melampaui engine-engine seperti itu
    • Saat membuat mesin pencari, masalah terbesar bukan QPS melainkan ukuran dataset yang diindeks. Jika struktur pencarian muat di memori satu mesin, latensi bisa mendekati nol dan secara praktis memberikan QPS tak terbatas
      Begitu lebih besar dari itu, dibutuhkan solusi kreatif, dan sejak saat itu berbagai trade-off mulai muncul
    • Saya penasaran apakah ini dirilis sebagai open source di suatu tempat
  • Salah satu dari banyak masalah saat melakukan pencarian di dalam Postgres adalah bahwa pencarian merupakan pekerjaan yang sangat memakan CPU, dan arahnya makin banyak memanfaatkan GPU. Idealnya, CPU basis data dibiarkan untuk pembaruan transaksional pada model data inti
    Saya sering melihat cluster ES dan Solr saat reindexing berjalan 100% di lebih dari 10 node, atau bahkan dalam kondisi normal memakai 30~50% di lebih dari 10 node. Basis data pasangannya, misalnya, bisa saja memakai instance AWS L/XL dengan data 50~100GB dan penggunaan CPU sekitar 30%
    Jika seluruh beban CPU pencarian dipindahkan ke DB utama, sekarang DB itu juga harus di-shard. Meski begitu, untuk side project, ekstensi PG untuk pencarian, recursive join, dan vector itu menyenangkan dan sederhana

    • Bukankah ini bisa diatasi dengan melakukan pencarian di read-only replica?
  • Dulu saya benar-benar pernah melakukan ini, dan berhasil membuatnya cukup cepat
    https://austingwalters.com/fast-full-text-search-in-postgres...
    Situs web saat ini adalah https://askhn.ai

  • Jika teknik seperti ini digabungkan dengan pgvector, kita juga bisa menemukan konten yang relevan lewat embedding. Rasanya cukup seperti sihir

    • Bisakah dijelaskan sedikit lebih detail atau diberi referensi yang layak dibaca?
    • Menarik melihat orang memilih jalan yang agak hacky seperti ini padahal bisa memakai sesuatu seperti Vespa. Dari sisi performa, relevansi, skalabilitas, dan pengalaman pengembang, menurut saya Vespa lebih baik beberapa orde besaran
  • Sebagai catatan, itu bukan "Dark" Vader melainkan Darth Vader. Saya juga dulu waktu kecil mengira itu "Dark"

    • Dalam beberapa terjemahan seperti bahasa Prancis, memang benar menjadi Dark Vador, jadi "kesalahan" itu jadi umum
    • Bagian itu sangat mengganggu dalam artikelnya sampai saya sulit fokus pada hal lain. Kalau sudah tahu kutipan Yoda, bagaimana bisa masih menulis Dark Vader?
  • Tulisan yang sangat bagus dan jelas. SQLite juga menyediakan fitur pengindeksan lanjutan dan stemming melalui plugin standar
    Untuk bahasa Inggris, SQLite juga bekerja dengan baik

    • Saya menemukan materi eksperimen dengan SQLite
      https://github.com/daitangio/knowledge
      Layak dicoba. Cukup kuat
    • Saya penasaran apakah ini juga bisa dilakukan dengan FDW. Jika hanya mereplikasi data yang menjadi target pencarian, karena penulis tidak akan banyak, mungkin bisa berjalan baik untuk data skala menengah
  • Ini tulisan yang bagus, tetapi bagian yang mengatakan PostgreSQL tidak mendukung fuzzy search agak kurang tepat. Ekstensi pg_trgm dan indeks trigram GIN mendukung use case fuzzy search seperti contoh di tulisan ini
    https://www.postgresonline.com/article_pfriendly/169.html
    Kueri bisa menjadi jauh lebih cepat, tetapi ada biaya berupa penggunaan memori yang lebih besar dan waktu kerja saat update yang meningkat