MySQL FULLTEXT Поиск по> 1 таблице - PullRequest
4 голосов
/ 21 марта 2009

В более общем случае этот вопрос , потому что я думаю, что он может быть интересен большему количеству людей ... Какой лучший способ выполнить полнотекстовый поиск по двум таблицам? Предположим, есть три таблицы, одна для программ (с submitter_id) и одна для тегов и описаний с object_id: внешние ключи, относящиеся к записям в программах. Мы хотим, чтобы submitter_id программ с определенным текстом в их тегах ИЛИ описаниях. Мы должны использовать МАТЧ ПРОТИВ по причинам, о которых я не буду здесь говорить. Не зацикливайтесь на этом аспекте.

programs
  id
  submitter_id
tags_programs
  object_id
  text
descriptions_programs
  object_id
  text

Следующие работы и исполнения выполняются примерно за 20 мс:

SELECT p.submitter_id
FROM programs p
WHERE p.id IN
    (SELECT t.object_id
    FROM titles_programs t
    WHERE MATCH (t.text) AGAINST ('china')
UNION ALL
    SELECT d.object_id
    FROM descriptions_programs d
    WHERE MATCH (d.text) AGAINST ('china'))

но я попытался переписать это как JOIN следующим образом, и он работает очень долго. Я должен убить его через 60 секунд.

SELECT p.id 
FROM descriptions_programs d, tags_programs t, programs p
WHERE (d.object_id=p.id AND MATCH (d.text) AGAINST ('china'))
OR    (t.object_id=p.id AND MATCH (t.text) AGAINST ('china'))

Просто из любопытства я заменил ИЛИ на AND. Это также работает в течение нескольких миллисекунд, но это не то, что мне нужно. Что не так с приведенным выше вторым запросом? Я могу жить с СОЮЗОМ и подвыборками, но я бы хотел понять.

Ответы [ 4 ]

5 голосов
/ 21 марта 2009

Присоединяйтесь после фильтров (например, объедините результаты), не пытайтесь присоединиться, а затем фильтровать.

Причина в том, что вы теряете использование своего полнотекстового индекса.

Разъяснение в ответ на комментарий: здесь я использую слово «присоединиться» в общем, не как JOIN, а как синоним слияния или объединения.

Я, по сути, говорю, что вы должны использовать первый (более быстрый) запрос или что-то в этом роде. Причина в том, что он быстрее, состоит в том, что каждый из подзапросов достаточно беспорядочный, поэтому БД может использовать полнотекстовый индекс этой таблицы для очень быстрого выбора. Соединение двух (предположительно намного меньших) наборов результатов (с UNION) также происходит быстро. Это значит, что все быстро.

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

1 голос
/ 21 марта 2009

На всякий случай, если вы не знаете: MySQL имеет встроенный оператор под названием EXPLAIN , который можно использовать, чтобы увидеть, что происходит под поверхностью. Об этом много статей, поэтому я не буду вдаваться в подробности, но для каждой таблицы приводится оценка количества строк, которые необходимо обработать. Если вы посмотрите на столбец «строки» в результате EXPLAIN для второго запроса, вы, вероятно, увидите, что количество строк довольно велико и, конечно, намного больше, чем в первом.

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

0 голосов
/ 21 марта 2009

Союз - верный путь. Объединение извлекает оба полнотекстовых индекса сразу и может умножить количество фактически выполненных проверок.

0 голосов
/ 21 марта 2009

Если вы присоединитесь к обеим таблицам, у вас будет много записей для проверки. Например, если в обеих таблицах по 100 000 записей, при их полном объединении вы получите 10 000 000 000 записей (10 миллиардов!).

Если вы измените ИЛИ на И, тогда вы позволите движку отфильтровывать все записи из таблицы describ__programs, которая не соответствует 'Китаю', и только , а затем объединяются с title_programs.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...