sql >> Databáze >  >> RDS >> Mysql

Jak optimalizovat MySQL Boolean Full-Text Search? (Nebo čím to nahradit?) - C#

Za prvé, měli byste si uvědomit, že podpora RDBMS pro fulltextové indexování je hack, který má vynutit technologii navrženou tak, aby umožňovala efektivní přístup ke strukturovaným datům pro práci s nestrukturovaným textem. (Ano, to je jen moje názor. V případě potřeby to mohu obhájit, protože oběma technologiím velmi dobře rozumím.;)

Co tedy lze udělat pro zlepšení výkonu vyhledávání?

Možnost jedna – „Nejlepší nástroj pro daný úkol“

Nejlepším způsobem, jak zvládnout fulltextové vyhledávání v korpusu dokumentů, je použití technologie speciálně navržené k tomu, jako je SOLR (Lucene) z Apache nebo Sphinx od err, Sfinga.

Z důvodů, které budou zřejmé níže, důrazně doporučuji tento přístup.

Možnost 2 – Předběžné načtení výsledků

Při vytváření textových vyhledávacích řešení je obvyklým přístupem indexovat všechny dokumenty do jediného prohledávatelného indexu, a přestože to může být nejvýhodnější, není to jediný přístup.

Za předpokladu, že to, co hledáte, lze snadno kvantifikovat do sady známých pravidel, můžete nabídnout více „řízený“ styl vyhledávání než jednoduše nekvalifikovaný fulltext. Mám tím na mysli to, že pokud by vaše aplikace mohla těžit z navádění uživatelů k výsledkům, můžete předem načíst různé sady výsledků na základě známé sady pravidel do jejich vlastních tabulek, a tak snížit objem prohledaných dat.

Pokud očekáváte, že většina vašich uživatelů bude mít prospěch ze známé sady vyhledávacích výrazů ve známém pořadí, můžete své uživatelské rozhraní pro vyhledávání vytvořit tak, aby tyto výrazy upřednostňovalo.

Za předpokladu, že většina uživatelů hledá různé automobily, můžete nabídnout předdefinovaná vyhledávání na základě modelu, roku, stavu atd. Vaše uživatelské rozhraní pro vyhledávání by bylo vytvořeno jako řada rozbalovacích nabídek, které uživatele „navedou“ ke konkrétním výsledkům.

Nebo pokud se většina vyhledávání bude týkat konkrétního hlavního tématu (řekněme „automobily“), můžete předdefinovat tabulku pouze těch záznamů, které jste dříve identifikovali jako související s automobily.

Oba tyto přístupy by snížily počet záznamů, které je třeba prohledávat, a prodloužily by tak dobu odezvy.

Možnost 3 – „Vyrobte si vlastní“

Pokud nemůžete do svého projektu integrovat technologii externího vyhledávání a předběžné načítání není možné, stále existují způsoby, jak výrazně zkrátit dobu odezvy na vyhledávací dotaz, liší se však podle toho, co musíte splnit a jak očekáváte, že bude vyhledávání prováděno. .

Pokud očekáváte, že uživatelé budou vyhledávat pomocí jednotlivých klíčových slov nebo frází a booleovských vztahů mezi nimi, můžete zvážit vytvoření vlastního „obrácený index “ vašeho korpusu. (To je to, co Boolean Full-Text Search od MySQL již dělá, ale když to uděláte sami, získáte větší kontrolu nad rychlostí i přesností vyhledávání.)

Chcete-li vytvořit invertovaný index z vašich stávajících dat:

Krok 1. Vytvořte tři tabulky

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

Poznámka:Toto je pouze náčrt. Při vytváření těchto tabulek budete chtít přidat indexy a omezení atd.

Tabulka ignorovaných slov se používá ke zmenšení velikosti vašeho indexu pouze na ta slova, která jsou důležitá pro očekávané dotazy uživatelů. Například je zřídka užitečné indexovat anglické články, jako jsou „a“, „an“, „the“, protože nemají užitečný význam pro vyhledávání klíčových slov.

Obvykle budete potřebovat seznam ignorovaných slov speciálně vytvořený podle potřeb vaší aplikace. Pokud nikdy neočekáváte, že uživatelé zahrnou do svých dotazů výrazy „červená“, „bílá“ nebo „modrá“ nebo pokud se tyto výrazy objeví v každém prohledávatelný záznam, budete je chtít přidat do seznamu ignorovaných slov.

Pokyny k používání vlastního seznamu ignorovaných slov v MySQL naleznete v poznámce na konci této zprávy.

Viz také:

Krok 2. Sestavení obráceného indexu

Chcete-li sestavit invertovaný index z vašich stávajících záznamů, budete muset (pseudokód):

    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
      }
    }
Více o stopových slovech:

Namísto použití konkrétního seznamu ignorovaných slov může test 'if(w není v ignorovaných slovech)' učinit jiná rozhodnutí, buď místo nebo jako doplněk k vašemu seznamu nepřijatelných slov.

Vaše aplikace může chtít odfiltrovat všechna slova kratší než 4 znaky nebo pouze zahrnout slova z předem definované sady.

Vytvořením vlastního obráceného indexu získáte mnohem větší a jemnější kontrolu nad vyhledáváním.

Krok 3. Dotaz na obrácený index pomocí SQL

Tento krok skutečně závisí na tom, jak očekáváte odeslání dotazů do vašeho indexu.

Pokud mají být dotazy „pevně zakódované“, můžete jednoduše sami vytvořit příkaz select, nebo pokud potřebujete podpořit dotazy zadané uživatelem, budete muset převést libovolný dotazovací jazyk, který si zvolíte, na příkaz SQL (obvykle pomocí jednoduchý analyzátor).

Za předpokladu, že chcete načíst všechny dokumenty odpovídající logickému dotazu '(word1 AND word2) OR word3', možný přístup může být:

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;

POZNÁMKA:Toto je jen první průchod z temene mé hlavy. Jsem si jistý, že existují efektivnější způsoby, jak převést booleovský výraz dotazu na účinný příkaz SQL, a vítám všechny návrhy na zlepšení.

Chcete-li hledat fráze, budete muset do obráceného indexu přidat pole, které bude reprezentovat pozici slova v jeho záznamu, a zahrnout to do vašeho SELECT.

A nakonec budete muset aktualizovat svůj obrácený index, když přidáváte nové záznamy nebo mažete staré.

Poslední slovo

"Fulltext search" spadá pod velmi rozsáhlou oblast výzkumu známou jako "Information Retrieval" nebo IR a existuje mnoho knih na toto téma, včetně

Více najdete na Amazonu.

Poznámky

Jak používat svůj vlastní seznam ignorovaných slov v MySQL

Chcete-li použít svůj vlastní seznam ignorovaných slov v MySQL:

  1. Vytvořte si vlastní seznam ignorovaných slov, jedno slovo na řádek, a uložte jej na známé místo na serveru, řekněme:/usr/local/lib/IR/stopwords.txt

  2. Upravte soubor my.cnf a přidejte nebo aktualizujte následující řádky:
        [mysqld]  
        ft_min_word_len=1    
        ft_max_word_len=40  
        ft_stopword_file=/usr/local/lib/IR/stopwords.txt
    

    který nastaví minimální a maximální délku zákonných slov na 1 a 40 a řekne mysqld, kde najde svůj vlastní seznam ignorovaných slov.

    (Poznámka:výchozí ft_max_word_len je 84, což je podle mého názoru dost přehnané a může způsobit indexování řady řetězců, které nejsou skutečnými slovy.)

  3. Restartujte mysqld

  4. Zrušte a znovu vytvořte všechny fulltextové související indexy



  1. Načíst výpis Postgres po vytvoření docker-compose up

  2. Proč byste neměli zakázat ONLY_FULL_GROUP_BY

  3. 2 způsoby, jak vypsat všechny spouštěče v databázi PostgreSQL

  4. chyba 1265. Data ve sloupci zkrácena při pokusu o načtení dat ze souboru txt