Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak zoptymalizować wyszukiwanie pełnotekstowe MySQL Boolean? (Lub czym go zastąpić?) - C#

Po pierwsze, powinieneś zdać sobie sprawę, że obsługa RDBMS dla indeksowania pełnotekstowego to hack, który ma na celu wymuszenie wydajnego dostępu do danych strukturalnych w celu radzenia sobie z tekstem nieustrukturyzowanym. (Tak, to tylko moje opinia. W razie potrzeby mogę go bronić, ponieważ doskonale rozumiem obie technologie.;)

Co więc można zrobić, aby poprawić wydajność wyszukiwania?

Opcja pierwsza – „Najlepsze narzędzie do zadania”

Najlepszym sposobem obsługi wyszukiwania pełnotekstowego w korpusie dokumentów jest użycie specjalnie zaprojektowanej do tego technologii, takiej jak SOLR (Lucene) z Apache lub Sphinx od błędu, Sfinks.

Z powodów, które staną się jasne poniżej, zdecydowanie polecam to podejście.

Opcja druga – wstępne wczytanie wyników

Podczas konstruowania tekstowych rozwiązań wyszukiwania, typowym podejściem jest indeksowanie wszystkich dokumentów w pojedynczym indeksie z możliwością przeszukiwania i chociaż może to być najwłaściwsze, nie jest to jedyne podejście.

Zakładając, że to, czego szukasz, można łatwo określić ilościowo w zestawie znanych reguł, możesz zaoferować bardziej „kierowany” styl wyszukiwania niż po prostu niekwalifikowany pełny tekst. Mam na myśli to, że jeśli Twoja aplikacja może skorzystać na sprowadzaniu użytkowników do wyników, możesz wstępnie załadować różne zestawy wyników oparte na znanym zestawie reguł do ich własnych tabel, a tym samym zmniejszyć ilość danych do przeszukiwania.

Jeśli spodziewasz się, że większość Twoich użytkowników skorzysta ze znanego zestawu wyszukiwanych haseł w znanej kolejności, możesz skonstruować interfejs wyszukiwania tak, aby faworyzować te hasła.

Zakładając więc, że większość użytkowników szuka różnych samochodów, możesz oferować wstępnie zdefiniowane wyszukiwania na podstawie modelu, rocznika, stanu itp. Interfejs wyszukiwania będzie utworzony jako seria rozwijanych menu, które „prowadzą” użytkowników do określonych wyników.

Lub jeśli większość wyszukiwań będzie dotyczyła określonego głównego tematu (np. „samochody”), możesz wstępnie zdefiniować tabelę zawierającą tylko te rekordy, które wcześniej zidentyfikowałeś jako związane z samochodami.

Oba te podejścia zmniejszyłyby liczbę rekordów do przeszukania, a tym samym wydłużyłyby czas odpowiedzi.

Opcja trzecia – „Rzuć swoją własną”

Jeśli nie możesz zintegrować zewnętrznej technologii wyszukiwania z projektem, a wstępne ładowanie nie wchodzi w grę, nadal istnieją sposoby na znaczne skrócenie czasu odpowiedzi na zapytania wyszukiwania, ale różnią się one w zależności od tego, co musisz osiągnąć i jak oczekujesz, że wyszukiwanie zostanie przeprowadzone .

Jeśli oczekujesz, że użytkownicy będą wyszukiwać przy użyciu pojedynczych słów kluczowych lub fraz oraz relacji logicznych między nimi, możesz rozważyć utworzenie własnego „odwrócony indeks ' twojego ciała. (To jest to, co już robi Boolean Full-Text Search MySQL, ale zrobienie tego samemu pozwala na większą kontrolę zarówno nad szybkością, jak i dokładnością wyszukiwania.)

Aby zbudować odwrócony indeks na podstawie istniejących danych:

Krok 1. Utwórz trzy tabele

    // 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  
    )

Uwaga:to tylko szkic. Będziesz chciał dodać indeksy i ograniczenia itp. podczas tworzenia tych tabel.

Tabela odrzucanych słów służy do zmniejszania rozmiaru indeksu tylko do tych słów, które mają znaczenie dla oczekiwanych zapytań użytkowników. Na przykład rzadko przydatne jest indeksowanie artykułów w języku angielskim, takich jak „a”, „an”, „the”, ponieważ nie wnoszą one użytecznego znaczenia do wyszukiwania słów kluczowych.

Zazwyczaj potrzebujesz listy odrzucanych słów specjalnie przygotowanej do potrzeb Twojej aplikacji. Jeśli nigdy nie oczekujesz, że użytkownicy będą umieszczać terminy „czerwony”, „biały” lub „niebieski” w swoich zapytaniach lub jeśli te terminy pojawiają się w każdym przeszukiwalny rekord, chciałbyś dodać je do swojej listy odrzucanych słów.

Zobacz notatkę na końcu tej wiadomości, aby uzyskać instrukcje dotyczące korzystania z własnej listy odrzucanych słów w MySQL.

Zobacz też:

Krok 2. Zbuduj indeks odwrócony

Aby zbudować odwrócony indeks z istniejących rekordów, musisz (pseudo-kod):

    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
      }
    }
Więcej o odrzucanych słowach:

zamiast używać konkretnej listy odrzucanych słów, test „jeśli(w nie jest odrzucanymi słowami)” może podejmować inne decyzje zamiast lub jako uzupełnienie listy niedopuszczalnych słów.

Twoja aplikacja może chcieć odfiltrować wszystkie słowa o długości poniżej 4 znaków lub tylko zawierać słowa z predefiniowanego zestawu.

Tworząc własny indeks odwrócony, zyskujesz znacznie większą i dokładniejszą kontrolę nad wyszukiwaniem.

Krok 3. Zapytanie o odwrócony indeks za pomocą SQL

Ten krok naprawdę zależy od tego, jak oczekujesz, że zapytania zostaną przesłane do Twojego indeksu.

Jeśli zapytania mają być „zakodowane na stałe”, możesz po prostu samodzielnie utworzyć instrukcję select lub jeśli potrzebujesz obsługiwać zapytania wprowadzane przez użytkownika, musisz przekonwertować wybrany język zapytań na instrukcję SQL (zazwyczaj robi się to za pomocą prosty parser).

Zakładając, że chcesz pobrać wszystkie dokumenty pasujące do logicznego zapytania „(słowo1 I słowo2) LUB słowo3”, możliwym podejściem może być:

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;

UWAGA:To tylko pierwsze przejście z czubka głowy. Jestem przekonany, że istnieją wydajniejsze sposoby przekształcania wyrażenia logicznego zapytania w wydajną instrukcję SQL i z zadowoleniem przyjmuję wszelkie sugestie dotyczące ulepszeń.

Aby wyszukiwać frazy, musisz dodać pole do odwróconego indeksu, aby reprezentować pozycję, w której słowo pojawiło się w jego rekordzie i uwzględnić to w SELECT.

I na koniec musisz zaktualizować swój odwrócony indeks, dodając nowe rekordy lub usuwając stare.

Ostateczne słowo

„Wyszukiwanie pełnotekstowe” należy do bardzo dużego obszaru badań znanego jako „Pobieranie informacji” lub IR i istnieje wiele książek na ten temat, w tym

Sprawdź Amazon po więcej.

Notatki

Jak korzystać z własnej listy odrzucanych słów w MySQL

Aby użyć własnej listy odrzucanych słów w MySQL:

  1. Utwórz własną listę odrzucanych słów, jedno słowo w wierszu, i zapisz ją w znanej lokalizacji na serwerze, powiedzmy:/usr/local/lib/IR/stopwords.txt

  2. Edytuj my.cnf, aby dodać lub zaktualizować następujące wiersze:
        [mysqld]  
        ft_min_word_len=1    
        ft_max_word_len=40  
        ft_stopword_file=/usr/local/lib/IR/stopwords.txt
    

    który ustawi minimalną i maksymalną długość legalnych słów odpowiednio na 1 i 40 oraz poinformuje mysqld, gdzie znaleźć niestandardową listę odrzucanych słów.

    (Uwaga:domyślna wartość ft_max_word_len to 84, co moim zdaniem jest dość nadmierne i może powodować indeksowanie ciągów ciągów, które nie są prawdziwymi słowami).

  3. Uruchom ponownie mysqld

  4. Upuść i odtwórz wszystkie indeksy związane z pełnym tekstem



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wstawka MySQL przy zduplikowanej aktualizacji dla klucza innego niż PODSTAWOWY

  2. Typ danych tablicy, ciąg znaków podziału,

  3. „0000-00-00 00:00:00” nie może być reprezentowane jako błąd java.sql.Timestamp

  4. Dodawanie czasu w PHP

  5. Zapytanie MySQL w celu przypisania unikalnej liczby losowej do każdego wiersza