Текстовый поиск в MySQL - производительность и альтернативы - PullRequest
0 голосов
/ 24 января 2012

У меня есть такой набор таблиц в MySQL (внешние ключи, на которые ссылается [table_name] _id):

Articles(id, author_id, title, date, broad_search, ...)
Keywords(id, article_id, keyword (varchar))
Authors(id, name, ...)
Attachments(id, article_id, url, ...)

Таблица, которая нас больше всего беспокоит, это «Ключевые слова», поэтому я упоминаю индексы только для нее:

id - Primary - BTREE
(article_id,keyword) - Unique - BTREE
keyword - BTREE
article_id - BTREE

Каждая статья имеет связанный список ключевых слов. В столбце "broad_search" в Articles указывается, может ли данная конкретная статья быть широко сопоставлена ​​с ключевыми словами (broad_search = 1) или должно быть точное совпадение ключевого слова (broad_search = 0). У меня есть запрос SELECT, который вытягивает список статей на основе ключевых слов, параметра broad_search и других критериев фильтрации.

$sql = "SELECT *
FROM Keywords k, Attachments at, Articles ar, Authors a (2 more tables)
WHERE 
((ar.broad_search=0 AND k.keyword = '$Keyword')
OR (ar.broad_search=1 AND (INSTR('$Keyword', k.keyword)>0 OR k.keyword like '%$Keyword%')))
AND at.article_id = ar.id
AND a.id = ar.author_id 
... (more conditions)
LIMIT 20";

Для статьи может быть задано либо совпадение, либо точное совпадение, и я пытаюсь получить их список по ключевому слову.

Точное совпадение просто. Но у широкого соответствия есть различные случаи, которые не позволяют мне использовать простой шаблон подстановки, такой как «% search_term%». Пример:

Keywords for a broad match article = {books, used books, reading books, popular book}
search term = new books

Теперь мы не можем использовать совпадение с подстановочной строкой mysql, поскольку '%new books%' не будет соответствовать ни одному из ключевых слов, но его необходимо найти, так как поисковый термин содержит подстроку ключевых слов (broad_search = 1). Итак, broad_search имеет 2 типа: search_term = "автомобили" в ключевом слове "подержанные автомобили" и поисковый термин = "подержанные автомобили" в ключевом слове "автомобили".

Если broad_search = 0, сделайте точное совпадение. Если broad_search = 1, сопоставьте оба случая:

 ((ar.broad_search=0 AND k.keyword = '$Keyword')
        OR (ar.broad_search=1 AND (INSTR('$Keyword', k.keyword)>0 OR k.keyword like '%$Keyword%')))

Запрос, который я написал, отлично справляется Но проблема в производительности. Таблица ключевых слов очень большая, 100 000 строк и продолжает расти. Кроме того, это приложение с высокой нагрузкой и убивает мой сервер из-за огромного количества запросов, которые оно получает.

Мне кажется, это не правильный способ выполнения текстового поиска. Я попытался просмотреть документы mysql в отношении полнотекстового поиска, но я не совсем понял, в чем заключается его применение и соответствует ли оно моим критериям поиска. Кроме того, я подумал, что Apache Lucene будет лучшим выбором, но я не использовал его ранее, поэтому не уверен (этот запрос выполняется в сценарии PHP).

Как мне это реализовать? Это проблема индексации, или функция MySQL INSTR неэффективна, или я должен использовать совершенно другой подход?

1 Ответ

1 голос
/ 24 января 2012

MySQL не поисковая система, это система управления базами данных отношений (RDBMS). Однако вы можете реализовать собственные инструменты MySQL для эмуляции возможностей полнотекстового поиска, таких как настройка таблицы поиска как MyISAM и добавление индекса FULLTEXT к столбцам, по которым вы хотите осуществлять поиск. Вы можете прочитать MySQL документы для получения дополнительной информации о том, как MySQL поддерживает полнотекстовый поиск.

Даже если у вас полнотекстовые поисковые запросы работают так, как вы хотите, вы все равно упустите целый набор функций, которые поддерживает настоящая поисковая система (Lucene). Такие функции, как фасеты, пространственный поиск, повышение результатов, взвешивание и т. Д. Я бы посоветовал вам ознакомиться с Apache SOLR , поскольку он поддерживает все эти функции и многие другие. Существует даже PHP SOLR API , который можно использовать для доступа к экземпляру SOLR.

Я не говорю о том, чтобы полностью отказаться от MySQL, но использую его по прямому назначению, чтобы постоянно хранить данные, к которым можно обращаться и которые можно использовать для заполнения индексов вашей поисковой системы. В SOLR даже есть встроенный обработчик импорта документов, который позволит вам установить запрос к базе данных, который будет использоваться при массовом импорте данных из базы данных MySQL.

Кривая обучения относительно высока, как и при изучении большинства новых технологий, но когда вы закончите, вы будете удивляться, как вы обходились без использования настоящего полнотекстового поискового движка.

...