Mysql
 sql >> база данни >  >> RDS >> Mysql

Как да оптимизираме MySQL Boolean пълнотекстово търсене? (Или с какво да го заменя?) - C#

Първо, трябва да разберете, че поддръжката на RDBMS за индексиране на пълен текст е хак, който да принуди технология, предназначена да позволи ефективен достъп до структурирани данни, да се справя с неструктуриран текст. (Да, това е само моето мнение. Ако е необходимо, мога да го защитя, тъй като разбирам и двете технологии изключително добре.;)

И така, какво може да се направи, за да се подобри ефективността при търсене?

Първи вариант – „Най-добрият инструмент за задачата“

Най-добрият начин за работа с пълнотекстово търсене в рамките на корпус от документи е използването на технологията, специално предназначена за това, като SOLR (Lucene) от Apache или Sphinx от err, Сфинкс.

Поради причини, които ще станат ясни по-долу, силно препоръчвам този подход.

Вариант втора – предварително зареждане на вашите резултати

Когато се създават текстови решения за търсене, обичайният подход е да се индексират всички документи в един индекс с възможност за търсене и въпреки че това може да е най-целесъобразно, това не е единственият подход.

Ако приемем, че това, което търсите, може лесно да се определи количествено в набор от известни правила, бихте могли да предложите повече „насочен“ стил на търсене, отколкото просто неквалифициран пълен текст. Това, което имам предвид с това, е, че ако приложението ви може да се възползва от насочването на потребителите към резултатите, можете предварително да заредите различни набори от резултати въз основа на известен набор от правила в техните собствени таблици и по този начин да намалите по-голямата част от данните, които трябва да се търсят.

Ако очаквате, че мнозинството от вашите потребители ще се възползват от известен набор от думи за търсене в известен ред, можете да създадете потребителския си интерфейс за търсене, за да предпочитате тези термини.

Така че, ако приемем, че по-голямата част от потребителите търсят различни автомобили, може да предложите предварително дефинирани търсения въз основа на модел, година, състояние и т.н. Вашият потребителски интерфейс за търсене ще бъде изработен като серия от падащи менюта, за да „насочва“ потребителите към конкретни резултати.

Или ако по-голямата част от търсенията са за конкретна основна тема (да речем „автомобили“), можете да дефинирате предварително таблица само с онези записи, които преди сте идентифицирали като свързани с автомобили.

И двата подхода биха намалили броя на записите, които трябва да се търсят, и така ще увеличат времето за отговор.

Вариант три – „Отвъртете сами“

Ако не можете да интегрирате технология за външно търсене във вашия проект и предварителното зареждане не е опция, все още има начини за значително подобряване на времето за отговор на заявката за търсене, но те се различават в зависимост от това, което трябва да постигнете и как очаквате да се извършват търсенията .

Ако очаквате потребителите да търсят с помощта на единични ключови думи или фрази и булеви връзки между тях, може да помислите да създадете свой собствен „обърнат индекс “ от вашия корпус. (Това вече прави булевото пълнотекстово търсене на MySQL, но ако го направите сами, ви позволява по-голям контрол върху скоростта и точността на търсенето.)

За да създадете обърнат индекс от съществуващите си данни:

Стъпка 1. Създайте три таблици

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

Забележка:Това е само скица. Ще искате да добавите индекси и ограничения и т.н., когато всъщност създавате тези таблици.

Таблицата със стоп думи се използва за намаляване на размера на вашия индекс само до онези думи, които имат значение за очакваните заявки на потребителите. Например, рядко е полезно да се индексират английски статии, като 'a', 'an', 'the', тъй като те не придават полезно значение за търсенето по ключови думи.

Обикновено ще ви е необходим списък със стоп думи, специфично изработен за нуждите на вашето приложение. Ако никога не очаквате потребителите да включват термините „червено“, „бяло“ или „синьо“ в своите заявки или ако тези термини се появяват във всеки запис с възможност за търсене, бихте искали да ги добавите към вашия списък с думи за спиране.

Вижте бележката в края на това съобщение за инструкции как да използвате вашия собствен списък със стоп думи в MySQL.

Вижте също:

Стъпка 2. Изградете обърнатия индекс

За да създадете обърнат индекс от съществуващите си записи, ще трябва (псевдокод):

    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
      }
    }
Повече за спирателните думи:

Вместо да използва конкретен списък с думи за спиране, тестът „if(w не е в спирателните думи)“ може да вземе други решения вместо или като допълнение към вашия списък с неприемливи думи.

Вашето приложение може да пожелае да филтрира всички думи с дължина по-малко от 4 знака или да включи думи от предварително дефиниран набор.

Създавайки свой собствен обърнат индекс, вие получавате много по-голям и по-фин контрол върху търсенето.

Стъпка 3. Запитване на обърнатия индекс с помощта на SQL

Тази стъпка наистина зависи от това как очаквате заявките да се подават към вашия индекс.

Ако заявките трябва да бъдат „твърдо кодирани“, можете просто сами да създадете оператора select или ако трябва да поддържате въведени от потребителя заявки, ще трябва да преобразувате какъвто и език на заявка да изберете в SQL израз (обикновено се извършва с помощта на прост анализатор).

Ако приемем, че искате да извлечете всички документи, съответстващи на логическата заявка „(word1 AND word2) OR word3“, възможен подход може да бъде:

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;

ЗАБЕЛЕЖКА:Това е само първо преминаване от върха на главата ми. Убеден съм, че има по-ефективни начини за преобразуване на булев израз на заявка в ефективен SQL израз и приветствам всички предложения за подобрение.

За да търсите фрази, ще трябва да добавите поле към обърнатия индекс, за да представите позицията, на която думата се е появила в записа й, и да вземете предвид това във вашия SELECT.

И накрая, ще трябва да актуализирате своя обърнат индекс, докато добавяте нови записи или изтривате стари.

Последна дума

„Търсене на пълен текст“ попада в много голяма област на изследване, известна като „Извличане на информация“ или IR и има много книги по темата, включително

Проверете Amazon за повече.

Бележки

Как да използвате свой собствен списък със спиращи думи в MySQL

За да използвате свой собствен списък със стоп думи в MySQL:

  1. Създайте свой собствен списък със спирателни думи, по една дума на ред и го запазете на известно място на вашия сървър, кажете:/usr/local/lib/IR/stopwords.txt

  2. Редактирайте my.cnf, за да добавите или актуализирате следните редове:
        [mysqld]  
        ft_min_word_len=1    
        ft_max_word_len=40  
        ft_stopword_file=/usr/local/lib/IR/stopwords.txt
    

    което ще зададе минималната и максималната дължина на юридическите думи съответно на 1 и 40 и ще каже на mysqld къде да намери вашия персонализиран списък със спиращи думи.

    (Забележка:ft_max_word_len по подразбиране е 84, което според мен е доста прекомерно и може да доведе до индексиране на низове, които не са истински думи.)

  3. Рестартирайте mysqld

  4. Изхвърлете и създайте отново всички индекси, свързани с пълен текст



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Използване на променлива в клауза LIMIT в MySQL

  2. SQL брой - не работи

  3. колона за актуализиране на mysql със стойност от друга таблица

  4. AttributeError:модулът 'mysql' няма атрибут 'connector'

  5. Django Multiple Databases Fallback към Master, ако Slave не работи