#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, я предполагаю, что мне нужно убедиться, что некоторые вещи рассмотрены в первую очередь. Я удовлетворен.