Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Bagaimana cara mengoptimalkan Pencarian Teks Lengkap Boolean MySQL? (Atau harus diganti dengan apa?) - C#

Pertama, Anda harus menyadari bahwa dukungan RDBMS untuk pengindeksan teks lengkap adalah peretasan untuk memaksa teknologi yang dirancang untuk memungkinkan akses yang efisien ke data terstruktur untuk menangani teks tidak terstruktur. (Ya, itu hanya saya pendapat. Jika diperlukan, saya dapat mempertahankannya karena saya memahami kedua teknologi dengan sangat baik.;)

Jadi, apa yang dapat dilakukan untuk meningkatkan kinerja penelusuran?

Opsi Satu - "Alat Terbaik Untuk Tugas"

Cara terbaik untuk menangani pencarian teks lengkap dalam kumpulan dokumen adalah menggunakan teknologi yang dirancang khusus untuk melakukannya, seperti SOLR (Lucene) dari Apache atau Sphinx dari err, Sphinx.

Untuk alasan yang akan menjadi jelas di bawah, saya sangat menyarankan pendekatan ini.

Opsi Dua - Pramuat Hasil Anda

Saat membangun solusi pencarian berbasis teks, pendekatan yang biasa dilakukan adalah mengindeks semua dokumen ke dalam satu indeks yang dapat dicari dan meskipun ini mungkin yang paling bijaksana, ini bukan satu-satunya pendekatan.

Dengan asumsi apa yang Anda cari dapat dengan mudah diukur ke dalam seperangkat aturan yang diketahui, Anda dapat menawarkan lebih banyak gaya pencarian "terpandu" daripada sekadar teks lengkap yang tidak memenuhi syarat. Yang saya maksud dengan ini adalah, jika aplikasi Anda mungkin mendapat manfaat dari mengelompokkan pengguna ke hasil, Anda dapat memuat berbagai set hasil sebelumnya berdasarkan seperangkat aturan yang diketahui ke dalam tabel mereka sendiri, dan dengan demikian mengurangi sebagian besar data yang akan dicari.

Jika Anda mengharapkan sebagian besar pengguna Anda akan mendapat manfaat dari kumpulan istilah penelusuran yang diketahui dalam urutan yang diketahui, Anda dapat membuat UI penelusuran untuk mendukung istilah tersebut.

Jadi dengan asumsi mayoritas pengguna mencari berbagai jenis mobil, Anda mungkin menawarkan pencarian yang telah ditentukan sebelumnya berdasarkan model, tahun, kondisi, dll. UI pencarian Anda akan dibuat sebagai serangkaian menu tarik-turun untuk "membimbing" pengguna ke hasil tertentu.

Atau jika sebagian besar penelusuran ditujukan untuk topik utama tertentu (misalnya 'mobil'), Anda dapat membuat tabel yang hanya berisi catatan yang sebelumnya Anda identifikasi terkait dengan mobil.

Kedua pendekatan ini akan mengurangi jumlah catatan yang akan dicari, sehingga meningkatkan waktu respons.

Opsi Tiga - "Gulung Sendiri"

Jika Anda tidak dapat mengintegrasikan teknologi pencarian eksternal ke dalam proyek Anda dan pramuat bukanlah suatu pilihan, masih ada cara untuk meningkatkan waktu respons permintaan pencarian, tetapi mereka berbeda berdasarkan apa yang perlu Anda capai dan bagaimana Anda mengharapkan pencarian dilakukan .

Jika Anda mengharapkan pengguna menelusuri menggunakan kata kunci atau frasa tunggal dan hubungan boolean di antara mereka, Anda dapat mempertimbangkan untuk membuat 'indeks terbalik ' dari tubuh Anda. (Inilah yang sudah dilakukan Pencarian Teks Lengkap Boolean MySQL, tetapi melakukannya sendiri memungkinkan kontrol yang lebih besar atas kecepatan dan akurasi pencarian.)

Untuk membuat indeks terbalik dari data yang ada:

Langkah 1. Buat tiga tabel

    // dict - a dictionary containing one row per unique word in corpus  
    create table dict (    
      id int primary key,  
      word varchar  
    )

    // invert - an inverted_index to map words to records in corpus  
    create table invert (    
      id int primary key,  
      rec_id int,  
      word_id int  
    )

    // stopwords - to contain words to ignore when indexing (like a, an, the, etc)
    create table stopwords ( 
      id int primary key,  
      word varchar  
    )

Catatan:Ini hanya sketsa. Anda akan ingin menambahkan indeks dan batasan, dll. saat Anda benar-benar membuat tabel ini.

Tabel stopwords digunakan untuk mengurangi ukuran indeks Anda menjadi hanya kata-kata yang penting bagi kueri yang diharapkan pengguna. Misalnya, jarang berguna untuk mengindeks artikel bahasa Inggris, seperti 'a', 'an', 'the', karena artikel-artikel tersebut tidak memberikan arti yang berguna bagi pencarian kata kunci.

Biasanya, Anda memerlukan daftar stopword dibuat secara khusus dengan kebutuhan aplikasi Anda. Jika Anda tidak pernah mengharapkan pengguna menyertakan istilah 'merah', 'putih', atau 'biru' dalam kueri mereka atau jika istilah ini muncul di setiap catatan yang dapat dicari, Anda ingin menambahkannya ke daftar stopword Anda.

Lihat catatan di akhir pesan ini untuk petunjuk penggunaan daftar stopword Anda sendiri di MySQL.

Lihat juga:

Langkah 2. Buat Indeks Terbalik

Untuk membuat indeks terbalik dari catatan yang ada, Anda harus (kode semu):

    foreach( word(w) in record(r) ) {
      if(w is not in stopwords) {
        if( w does not exist in dictionary) {
          insert w to dictionary at w.id
        }
        insert (r.id, w.id) into inverted_index
      }
    }
Lebih lanjut tentang stopword:

Alih-alih menggunakan daftar stopword tertentu, pengujian 'jika(w tidak ada dalam stopwords)' dapat membuat keputusan lain sebagai pengganti atau sebagai tambahan untuk daftar kata yang tidak dapat diterima.

Aplikasi Anda mungkin ingin memfilter semua kata yang panjangnya kurang dari 4 karakter atau hanya menyertakan kata-kata dari set yang telah ditentukan.

Dengan membuat indeks terbalik Anda sendiri, Anda mendapatkan kontrol yang jauh lebih besar dan lebih halus atas pencarian.

Langkah 3. Kueri Indeks Terbalik Menggunakan SQL

Langkah ini sangat bergantung pada bagaimana Anda mengharapkan kueri dikirimkan ke index.

Jika kueri akan menjadi 'hard-coded', Anda cukup membuat pernyataan pilih sendiri atau jika Anda perlu mendukung kueri yang dimasukkan pengguna, Anda harus mengonversi bahasa kueri apa pun yang Anda pilih menjadi pernyataan SQL (biasanya dilakukan menggunakan pengurai sederhana).

Dengan asumsi Anda ingin mengambil semua dokumen yang cocok dengan kueri logis '(word1 AND word2) OR word3', pendekatan yang mungkin adalah:

CREATE TEMPORARY TABLE temp_results ( rec_id int, count int ) AS 
    ( SELECT rec_id, COUNT(rec_id) AS count 
      FROM invert AS I, dict AS D 
      WHERE I.word_id=D.id AND (D.word='word1' OR D.word='word2') 
      GROUP BY I.rec_id 
      HAVING count=2
    ) 
    UNION (
      SELECT rec_id, 1 AS count 
      FROM invert AS I, dict AS D
      WHERE I.word_id=D.id AND D.word='word3'
    );

SELECT DISTINCT rec_id FROM temp_results;

DROP TABLE temp_results;

CATATAN:Ini hanya umpan pertama dari atas kepala saya. Saya yakin ada cara yang lebih efisien untuk mengubah ekspresi kueri boolean menjadi pernyataan SQL yang efisien dan menyambut setiap dan semua saran untuk perbaikan.

Untuk menelusuri frasa, Anda harus menambahkan bidang ke indeks terbalik untuk mewakili posisi kata yang muncul dalam catatannya dan memasukkannya ke dalam SELECT Anda.

Dan terakhir, Anda harus memperbarui indeks terbalik saat Anda menambahkan catatan baru atau menghapus yang lama.

Kata Akhir

"Pencarian teks lengkap" berada di bawah area penelitian yang sangat luas yang dikenal sebagai "Penemuan Informasi" atau IR dan ada banyak buku tentang masalah ini, termasuk

Periksa Amazon untuk informasi lebih lanjut.

Catatan

Cara Menggunakan Daftar Stopword Anda Sendiri di MySQL

Untuk menggunakan daftar stopword Anda sendiri di MySQL:

  1. Buat daftar stopword Anda sendiri, satu kata per baris, dan simpan ke lokasi yang diketahui di server Anda, misalnya:/usr/local/lib/IR/stopwords.txt

  2. Edit my.cnf untuk menambahkan atau memperbarui baris berikut:
        [mysqld]  
        ft_min_word_len=1    
        ft_max_word_len=40  
        ft_stopword_file=/usr/local/lib/IR/stopwords.txt
    

    yang akan mengatur panjang minimum dan maksimum kata legal masing-masing menjadi 1 dan 40, dan memberi tahu mysqld di mana menemukan daftar stopword khusus Anda.

    (Catatan:default ft_max_word_len adalah 84, yang menurut saya cukup berlebihan dan dapat menyebabkan rangkaian string yang bukan kata sebenarnya diindeks.)

  3. Mulai ulang mysqld

  4. Lepaskan dan buat ulang semua indeks terkait teks lengkap



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Daftar Proses MySql diisi dengan Entri Tidur yang mengarah ke Terlalu Banyak Koneksi?

  2. Pembaruan MySQL dengan pilih dari tabel lain

  3. Bagaimana cara memasukkan nilai dalam array PHP ke tabel MySQL?

  4. Jalankan skrip SQL untuk membuat tabel dan baris

  5. Cara Mendapatkan row_number di MySQL