MySQL "OR MATCH" зависает (очень медленно) на нескольких таблицах - PullRequest
2 голосов
/ 23 мая 2010

После изучения того, как выполнять полнотекстовый поиск MySQL, было рекомендовано решение для нескольких таблиц OR MATCH, а затем выполнить другой вызов базы данных. Вы можете видеть это в моем запросе ниже.

Когда я делаю это, он просто застревает в «занятом» состоянии, и я не могу получить доступ к базе данных MySQL.

SELECT 
 a.`product_id`, a.`name`, a.`slug`, a.`description`, b.`list_price`, b.`price`, c.`image`, c.`swatch`, e.`name` AS industry, 
 MATCH( a.`name`, a.`sku`, a.`description` ) AGAINST ( '%s' IN BOOLEAN MODE )     AS relevance 
FROM 
 `products` AS a LEFT JOIN `website_products` AS b 
  ON (a.`product_id` = b.`product_id`) 
 LEFT JOIN ( SELECT `product_id`, `image`, `swatch` FROM `product_images` WHERE `sequence` = 0) AS c 
  ON (a.`product_id` = c.`product_id`) 
 LEFT JOIN `brands` AS d 
  ON (a.`brand_id` = d.`brand_id`) 
 INNER JOIN `industries` AS e ON (a.`industry_id` = e.`industry_id`) 
WHERE 
 b.`website_id` = %d
 AND b.`status` = %d
 AND b.`active` = %d 
 AND MATCH( a.`name`, a.`sku`, a.`description` ) AGAINST ( '%s' IN BOOLEAN MODE ) 
  OR MATCH ( d.`name` ) AGAINST ( '%s' IN BOOLEAN MODE )
GROUP BY a.`product_id` 
ORDER BY relevance DESC 
LIMIT 0, 9 

Любая помощь будет принята с благодарностью.


EDIT

Все задействованные таблицы - MyISAM, utf8_general_ci.

Вот оператор EXPLAIN SELECT:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 16076 Using temporary; Using filesort
1 PRIMARY b ref product_id product_id 4 database.a.product_id 2  
1 PRIMARY e eq_ref PRIMARY PRIMARY 4 database.a.industry_id 1  
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 23261  
1 PRIMARY d eq_ref PRIMARY PRIMARY 4 database.a.brand_id 1 Using where
2 DERIVED product_images ALL NULL NULL NULL NULL 25933 Using where

Я не знаю, как сделать это аккуратнее - извините за это


UPDATE

возвращает запрос через 196 секунд (я думаю, правильно). Запрос без нескольких таблиц занимает около .56 секунд (что, как я знаю, очень медленно, мы планируем вскоре перейти на solr или sphinx), но 196 секунд ??

Если бы мы могли добавить число к релевантности, если бы оно было в названии бренда (d. name), это также сработало бы

1 Ответ

4 голосов
/ 24 мая 2010

Я обнаружил, что 2 вещи резко замедлили мой запрос и исправили их.

Чтобы ответить на первую проблему, требовались круглые скобки вокруг всего «МАТЧА ПРОТИВ ИЛИ МАТЧ ПРОТИВ»:

WHERE 
    b.`website_id` = %d
    AND b.`status` = %d
    AND b.`active` = %d 
    AND ( 
        MATCH( a.`name`, a.`sku`, a.`description` ) AGAINST ( '%s' IN BOOLEAN MODE ) 
        OR MATCH ( d.`name` ) AGAINST ( '%s' IN BOOLEAN MODE )
    )

Я не понял, как использовать EXPLAIN SELECT, но это очень помогло, так что спасибо! Это уменьшило первое число с 16076 строк до 143. Затем я заметил два других с более чем 23 и 25 тысячами строк. Это было причиной из этой строки:

LEFT JOIN ( SELECT `product_id`, `image`, `swatch` FROM `product_images` WHERE `sequence` = 0) AS c 
    ON (a.`product_id` = c.`product_id`)

Была причина, по которой я делал это в первую очередь, которая затем изменилась. Когда я изменил его, я не понял, что смогу сделать обычный LEFT JOIN:

LEFT JOIN `product_images` AS c 
    ON (a.`product_id` = c.`product_id`)

Это делает мой последний запрос таким: (и НАМНОГО быстрее прошел с 196 секунд до 0,0084 или около того)

SELECT 
    a.`product_id`, a.`name`, a.`slug`, a.`description`, b.`list_price`, b.`price`, 
    c.`image`, c.`swatch`, e.`name` AS industry, 
    MATCH( a.`name`, a.`sku`, a.`description` ) AGAINST ( '%s' IN BOOLEAN MODE ) AS relevance 
FROM 
    `products` AS a LEFT JOIN `website_products` AS b 
        ON (a.`product_id` = b.`product_id`) 
    LEFT JOIN `product_images` AS c 
        ON (a.`product_id` = c.`product_id`) 
    LEFT JOIN `brands` AS d 
        ON (a.`brand_id` = d.`brand_id`) 
    INNER JOIN `industries` AS e 
        ON (a.`industry_id` = e.`industry_id`) 
WHERE 
    b.`website_id` = %d
    AND b.`status` = %d
    AND b.`active` = %d
    AND c.`sequence` = %d
    AND ( 
        MATCH( a.`name`, a.`sku`, a.`description` ) AGAINST ( '%s' IN BOOLEAN MODE ) 
        OR MATCH( d.`name` ) AGAINST( '%s' IN BOOLEAN MODE ) 
    )
GROUP BY a.`product_id` 
ORDER BY relevance DESC 
LIMIT 0, 9

О, и даже до того, как я выполнял полнотекстовый поиск по нескольким таблицам, это занимало около 1/2 секунды. Это намного улучшилось.

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