Полнотекстовый поиск MySQL, но с использованием LIKE

#mysql #sql

#mysql #sql

Вопрос:

Недавно я выполняю несколько поисков строк из таблицы, содержащей около 50 тысяч строк, я бы сказал, довольно больших, но не настолько. Я выполнял несколько вложенных запросов для чего-то вроде «поиска в результатах». Я использовал оператор LIKE, чтобы получить совпадение с искомым ключевым словом.

Я наткнулся на полнотекстовый поиск MySQL, который я попробовал, поэтому я добавил полнотекстовый индекс в свой str столбец. Я знаю, что полнотекстовый поиск не работает с виртуально созданными таблицами или даже с Views поэтому запросы с подвыборками не подойдут. Я упоминал, что выполнял вложенные запросы, пример:

 SELECT s2.id, s2.str 
FROM 
    (
    SELECT s1.id, s1.str 
    FROM 
        (
         SELECT id, str 
         FROM strings 
         WHERE str LIKE '%term%'
         ) AS s1 
    WHERE s1.str LIKE '%another_term%'
    ) AS s2 
WHERE s2.str LIKE '%a_much_deeper_term%';
  

На самом деле это пока не применяется ни к какому коду, я просто проводил несколько тестов. Кроме того, поиск по строкам, подобным этому, может быть легко осуществлен с помощью Sphinx (с точки зрения производительности), но давайте рассмотрим, что Sphinx недоступен, и я хочу знать, как это будет хорошо работать в чистом SQL-запросе. Выполнение этого запроса в таблице без добавления полнотекста занимает около 2.97 secs . (зависит от поискового запроса). Однако выполнение этого запроса в таблице с полным текстом, добавленным в str столбец, завершилось примерно за 104 мс, что быстро (я думаю?).

Мой вопрос прост: допустимо ли использовать LIKE или вообще рекомендуется использовать его в таблице с добавленным полнотекстом, когда обычно мы используем операторы MATCH и AGAINST?

Спасибо!

Комментарии:

1. Вы всегда можете использовать полнотекстовый индекс в самом внутреннем запросе nester SQL. Конечно, это зависит от того, ищете ли вы слова wole.

2. @vbence потрясающе, я только что попробовал, что для самого внутреннего запроса результат завершается примерно за 15 мс. это на моем локальном хостинге, кстати, но это еще быстрее, заменив, ГДЕ str КАК ‘%term%’, на ГДЕ MATCH(str) ПРОТИВ(‘term’) 🙂

3. Большой вопрос в том, ищете ли вы только полные слова?

4. @vbence нет, совпадение строк со строками. Но вы правы, если это поиск по полному слову, полезно использовать fullindex в самой внутренней части. Спасибо, что напомнили, что

Ответ №1:

В этом случае вам не обязательно нужны дополнительные выборки. Вы можете просто использовать:

 SELECT id, str
FROM item_strings
WHERE str LIKE '%term%'
   AND str LIKE '%another_term%'
   AND str LIKE '%a_much_deeper_term%'
  

… но также возникает хороший вопрос: порядок, в котором вы исключаете строки. Я предполагаю, что MySQL достаточно умен, чтобы предположить, что самый длинный термин будет самым ограничительным, поэтому, начиная с a_much_deeper_term , он удалит большинство записей, а затем выполнит дополнительное сравнение только для нескольких строк. — В отличие от этого, если вы начнете с term , вы, вероятно, получите много возможных записей, тогда вам придется сравнить их с st терминов.

Интересная часть заключается в том, что вы можете принудительно задать порядок, в котором выполняется сравнение, используя ваш оригинальный пример подвыборки. Это дает возможность принять решение, какой термин является наиболее ограничительным, основываясь не только на длине, но, например:

  • соотношение согласных и гласных
  • самая длинная цепочка согласных в слове
  • наиболее используемая гласная в слове

…и т.д. Вы также можете применить некоторые эвристики, основанные на типе текстовой информации, с которой вы работаете.

Редактировать:

Это всего лишь предположение, но можно было бы применить LIKE к words в самом полнотекстовом индексе. Затем сопоставьте строки с индексом, как если бы вы выполнили поиск полных слов.

Я не уверен, что это действительно сделано, но это было бы разумно осуществить специалистам MySQL. Также обратите внимание, что эту теорию можно использовать только в том случае, если в полнотекстовом поиске действительно присутствуют все возможные совпадения. Для этого вам нужно, чтобы:

  • Размер вашего шаблона поиска должен быть не менее длины слова miimal. (Например, если вы выполняете поиск %id% , то это также может быть частью слова из 3 букв, которое исключается полнотекстовым индексом формы по умолчанию).
  • Ваш шаблон поиска не должен быть подстрокой какого-либо из перечисленных исключенных слов, например: and, of и т.д.
  • Ваш шаблон не должен содержать никаких специальных символов.

Комментарии:

1. Интересно, я предполагаю, что я усложняю это из-за подвыборок, которые у меня были, когда это может быть достигнуто с помощью одного запроса, и вы попадаете в цель, имея его, это строго определяет порядок сравнения. Я попробовал это, и это не имеет большого значения с точки зрения скорости. Теперь вопрос в том, когда таблица применяется с полнотекстовым индексом, используется ли LIKE допустимо и правильно , как если бы таблица была просто проиндексирована для ускорения?

2. @tradyblix Я добавил новую мысль к своему ответу относительно LIKE и FULLTEXT .

3. Понял, так что теоретически это возможно, но, очевидно, следует иметь в виду некоторые вещи, которые могут повлиять на поиск. Спасибо, что указали на это, те 3 вещи, которые вы упомянули, — это вещи, о которых я никогда не думал в случае ПОЛНОТЕКСТОВОГО индекса и при использовании LIKE с ним. Вполне вероятно, что если я захочу использовать LIKE, я предполагаю, что мне нужно убедиться, что некоторые вещи рассмотрены в первую очередь. Я удовлетворен.