SQL-запрос занимает слишком много времени - PullRequest
1 голос
/ 19 мая 2010

Я пытаюсь оптимизировать SQL-запрос, указанный ниже.
Это в основном код поисковой системы, который извлекает продукты на основе названия продуктов. Он также проверяет номер модели продукта и включен ли он.
Это выполняется примерно за 1,6 секунды, когда я запускаю его непосредственно через инструмент phpMyAdmin, но в общей сложности занимает около 3 секунд для загрузки вместе с файлом PHP, в котором он находится.

Мне нужно добавить функцию поиска по категориям, и теперь, когда происходит сбой сервера MySQL, HELP!

Justin

SELECT DISTINCT
    p.products_id,
    p.products_image,
    p.products_price,
    s.specials_new_products_price,
    p.products_weight,
    p.products_unit_quantity,
    pd.products_name,
    pd.products_img_alt,
    pd.products_affiliate_url
FROM
    products AS p
    LEFT JOIN
        vendors v
    ON
        v.vendors_id = p.vendors_id
    LEFT JOIN
        specials AS s
    ON
        s.products_id = p.products_id
        AND
        s.status = 1,
    categories AS c,
    products_description AS pd,
    products_to_categories AS p2c
WHERE
    (
        (
            pd.products_name LIKE '%cleaning%'
            AND
            pd.products_name LIKE '%supplies%'
        )
        OR
        (
            p.products_model LIKE '%cleaning%'
            AND
            p.products_model LIKE '%supplies%'
        )
        OR
        p.products_id = 'cleaning supplies'
        OR
        v.vendors_prefix = 'cleaning supplies'
        OR
            CONCAT (CAST (v.vendors_prefix AS CHAR), '-', CAST (p.products_id AS CHAR)) = 'cleaning supplies'
    )
    AND
    p.products_status = '1'
    AND
    c.categories_status = '1'
    AND
    p.products_id = pd.products_id
    AND
    p2c.products_id = pd.products_id
    AND
    p2c.categories_id = c.categories_id
ORDER BY
    pd.products_name

Ответы [ 2 ]

3 голосов
/ 20 мая 2010
left join specials as s on s.products_id = p.products_id and s.status = 1,

там у вас полное сканирование таблицы. Данные такого типа (tinyint, true / false) плохо обрабатываются InnoDB. В Oracle у вас есть что-то вроде растрового индекса, что хорошо для индексов с низкой селективностью. Вы можете использовать подзапрос, в вашем месте, что-то вроде этого:

...
where 
   p.product_id IN (SELECT S.status FROM specials s WHERE s.status = 1)
AND
   (
          ( pd.products_name like '%cleaning%' and pd.products_name like '%supplies%' ) or 
...

Затем вы молитесь, чтобы кеш запросов кешировал результаты этого подзапроса.

ПОЖАЛУЙСТА, ОБЪЯСНИТЕ!

0 голосов
/ 20 мая 2010
select p.products_id, p.products_image, p.products_price, 
    p.products_weight, p.products_unit_quantity, 
    s.specials_new_products_price, 
    pd.products_name, pd.products_img_alt, pd.products_affiliate_url 
from products as p 
    left join vendors v ON v.vendors_id = p.vendors_id
    left join specials as s on s.products_id = p.products_id, 
    left join products_description as pd on pd.products_id = p.products_id
    left join products_to_categories as p2c on p2c.products_id = p.products_id 
    left join categories as c on c.categories_id = p2c.categories_id
where 
       (
          ( pd.products_name like '%cleaning%' and pd.products_name like '%supplies%' ) or 
          ( p.products_model like '%cleaning%' and p.products_model like '%supplies%' ) or 
          p.products_id = 'cleaning supplies' or 
          v.vendors_prefix = 'cleaning supplies' or 
          CONCAT( CAST(v.vendors_prefix as char), '-', CAST(p.products_id as char) ) = 'cleaning supplies'
       ) 
    and p.products_status = '1' 
    and s.status = 1
    and c.categories_status = '1'
group by p.products_id
order by pd.products_name

Убедитесь, что установлены следующие индексы:

create index prod_prodid_status on products(products_id, products_status);
create index vendors_vendorid on vendors(vendors_id);
create index specials_prodid_status on vendors(products_id, `status`);
create index prod_desc_prodid_prodname on products_description(products_id, products_name);
create index prod_cat_prodid_catid on products_to_categories(products_id, categories_id);
create index categories_catid_status on categories(categories_id, categories_status);

И я надеюсь, что все поля с «id» в их именах являются целыми числами

...