2010-09-15 6 views
0

мне нужен запрос, который будет выбрать только один (GROUP BY phi.id_product) изображения для каждого продукта и этот образ должен быть один с (внутренним SELECT с ORDER BY заявление) в наивысший приоритет.Оптимизировать JOIN SQL запрос с дополнительным SELECT,

приоритет сохраняется в N: M отношение таблица называется product_has_image

Я создал запрос, но это около 3 Натальи принимает секунды для выполнения, и мне нужно оптимизировать. Вот оно:

SELECT p.*, i.id AS imageid 
FROM `product` p JOIN `category` c on c.`id` = p.`id_category` 
LEFT OUTER JOIN (SELECT id_product, id_image FROM 
`product_has_image` ORDER BY priority DESC) phi ON p.id = phi.id_product 
LEFT OUTER JOIN `image` i ON phi.id_image = i.id 
WHERE (c.`id_parent` = 2 OR c.`id` = 2) 
GROUP BY phi.id_product 

Индексы, которые я считаю важными в этом запросе, являются:

image (PRIMARY id) 
product_has_image (PRIMARY id_product, id_image; INDEX id_product; INDEX id_image) 
product (PRIMARY id, id_category; INDEX id_category) 
category (PRIMARY id; INDEX id_parent) 

Большую часть времени занимает соединения таблиц с помощью SELECT, заявление, которое требуется для сортировки.

Соединение с LEFT JOIN [product_has_image] phi ON p.id = phi.id_product происходит намного быстрее, но не присваивает изображение с наивысшим приоритетом.

Любая помощь будет оценена по достоинству.

+0

Можете ли вы опубликовать план выполнения? –

+0

Привет, спасибо за ваш ответ. После создания представления он занимает около 0,3 - 0,5 секунды на моей машине, и он еще быстрее на сервере. –

ответ

1

Переформатированный для чувствительности. , ,

SELECT p.*, i.id AS imageid 
FROM `product` p 
INNER JOIN `category` c on (c.`id` = p.`id_category`) 
LEFT OUTER JOIN (SELECT id_product, id_image 
       FROM `product_has_image` 
       ORDER BY priority DESC) phi 
      ON (p.id = phi.id_product) 
LEFT OUTER JOIN `image` i 
      ON (phi.id_image = i.id) 
WHERE (c.`id_parent` = 2 OR c.`id` = 2) 
GROUP BY phi.id_product 

Не видя план выполнения или DDL, я предполагаю (Дрожь), что проблема, скорее всего, внутренний выбор/сортировки. Если вы создаете вид

create view highest_priority_images as 
select id_product, max(priority) 
from product_has_image 
group by id_product 

Затем вы можете заменить этот внутренний SELECT ... ORDER BY с SELECT ... INNER JOIN на этой точке зрения. Это уменьшит мощность, поэтому я ожидаю, что он будет работать быстрее.

Проводка DDL поможет.

0

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

SELECT p.*, i.id AS imageid 
FROM `product` p 
    INNER JOIN `category` c ON c.id = p.id_category 

    /* a list of `id_product`s with their highest priorities 
    from `product_has_image` */ 
    LEFT OUTER JOIN (
    SELECT id_product, MAX(priority) AS max_priority 
    FROM `product_has_image` 
    GROUP BY id_product 
) m ON p.id = m.id_product 

    /* now joining `product_has_image` again, using 
    m.`max_priority` for additional filtering */ 
    LEFT OUTER JOIN `product_has_image` phi 
    ON p.id = phi.id_product AND m.max_priority = phi.priority 

    /* if you only select `id` from `image`, you can use 
    phi.`id_image` instead and remove this join */ 
    LEFT OUTER JOIN `image` i ON phi.id_image = i.id 

WHERE c.id_parent = 2 OR c.id = 2 
0

Не можете проверить это сейчас, но не было бы возможно сделать это?

SELECT p.*, i.id AS imageid 
FROM `product` p JOIN `category` c on c.`id` = p.`id_category` 
LEFT JOIN `product_has_image` phi ON p.id = phi.id_product 
LEFT OUTER JOIN `image` i ON phi.id_image = i.id 
WHERE (c.`id_parent` = 2 OR c.`id` = 2) 
GROUP BY phi.id_product 
ORDER BY phi.priority DESC 

Сделайте это в обычном порядке и порядке по phi.priority.

Смежные вопросы