@TsSaltan

Как оптимизировать/объединить запрос sql (полнотекстовый поиск)?

Нужно произвести полнотекстовый поиск как по заголовкам товаров, так и по заголовкам категорий. В случае совпадения будет возвращена выборка id этих товаров.

Вот поиск по заголовкам категорий
SELECT `id` FROM `object` obj
	JOIN `category` cat ON MATCH(cat.`title`) AGAINST (?)
	JOIN `obj2cat` obj2 ON obj2.`cat` = cat.`tid` 
	WHERE obj.`id` = obj2.`obj`

Выполняется за сотые доли секунды

Поиск по заголовкам товаров
SELECT `id` FROM `object` obj  WHERE MATCH(obj.`title`) AGAINST (?)

Также выполняется быстро

Но если их объединить
SELECT `id` FROM `object` obj
	JOIN `category` cat ON MATCH(cat.`title`) AGAINST (?)
	JOIN `obj2cat` obj2 ON obj2.`cat` = cat.`tid` 
	WHERE (
		obj.`id` = obj2.`obj`
		OR
		MATCH(obj.`title`) AGAINST (?)
	)

Время выполнения составляет пару десятков минут :(
Где я ошибся? Индексы на месте

EXPLAIN последнего запроса
array (
  0 => 
  array (
    'id' => 1,
    'select_type' => 'SIMPLE',
    'table' => 'cat',
    'type' => 'fulltext',
    'possible_keys' => 'PRIMARY,title',
    'key' => 'title',
    'key_len' => '0',
    'ref' => '',
    'rows' => 1,
    'Extra' => 'Using where',
  ),
  1 => 
  array (
    'id' => 1,
    'select_type' => 'SIMPLE',
    'table' => 'obj',
    'type' => 'ALL',
    'possible_keys' => 'PRIMARY',
    'key' => NULL,
    'key_len' => NULL,
    'ref' => NULL,
    'rows' => 4604,
    'Extra' => '',
  ),
  2 => 
  array (
    'id' => 1,
    'select_type' => 'SIMPLE',
    'table' => 'obj2',
    'type' => 'ALL',
    'possible_keys' => 'obj',
    'key' => NULL,
    'key_len' => NULL,
    'ref' => NULL,
    'rows' => 14676,
    'Extra' => 'Using where',
  ),
)
  • Вопрос задан
  • 2326 просмотров
Решения вопроса 1
@hurgadan
попробуйте
SELECT `id` FROM `object` obj
  JOIN `category` cat ON MATCH(cat.`title`) AGAINST (?)
  JOIN `obj2cat` obj2 ON obj2.`cat` = cat.`tid` 
  WHERE obj.`id` = obj2.`obj`
UNION
SELECT `id` FROM `object` obj  WHERE MATCH(obj.`title`) AGAINST (?)
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Melkij
@Melkij
PostgreSQL DBA
Первый раз вижу джойн по полнотекстовому поиску.
Хотя бы так попробуйте:
SELECT `id` FROM `object` obj
  JOIN `category` cat ON obj.`id` = obj2.`obj`
  JOIN `obj2cat` obj2 ON obj2.`cat` = cat.`tid` 
  WHERE (
    MATCH(cat.`title`) AGAINST (?)
    OR
    MATCH(obj.`title`) AGAINST (?)
  )


Если версия mysql актуальная (емнип, в 5.5 правили подзапросы). то можно попробовать:
SELECT `id` FROM `object` obj  WHERE MATCH(obj.`title`) AGAINST (?) or tid in (SELECT `tid` FROM `category` cat
  JOIN `obj2cat` obj2 ON obj2.`cat` = cat.`tid` -- мог неверно понять вашу структуру
  WHERE MATCH(cat.`title`) AGAINST (?) )
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
SELECT `obj`.`id` 
  FROM `object` AS `obj`
  JOIN `obj2cat` ON `obj2cat`.`obj` = `obj`.`id`
  JOIN `category` AS `cat` ON `cat`.`id` = `obj2cat`.`cat`
  WHERE MATCH(`cat`.`title`) AGAINST (?)
    OR MATCH(`obj`.`title`) AGAINST (?)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы