2014-02-03 5 views
0

Я думаю, что решение для моей проблемы не должно быть затруднено, но у меня появляется головная боль, так как я не могу найти решение самостоятельно.Оптимизация группы по запросу

Для веб-магазина я пытаюсь создать простой запрос, который выбирает самую низкую и самую высокую цену для всех продуктов определенной категории. Теперь проблема, я имею прямо сейчас, состоит в том, что почти все продукты имеют разные типы (скажем, 40-дюймовый телевизор, 42-дюймовый телевизор, 46 дюймов). Теперь я хотел бы использовать только самую низкую цену для каждого product_id, когда я пытаюсь получить самую низкую и максимальную цену всех продуктов. Мне удалось это сделать, однако запрос слишком медленный из-за предложения Group By. Запрос занимает около 40 секунд. Любые идеи по оптимизации этого запроса?

SELECT MIN(product_price), MAX(product_price) 
FROM products_inventory 
WHERE inventory_id IN (
    SELECT pi.inventory_id 
    FROM products_inventory pi 
    JOIN products p ON p.product_id = pi.product_id 
    JOIN category_products cp ON cp.product_id = p.product_id 
    WHERE cp.category_id IN (4,5,6,118) 
    GROUP BY product_id 
    ORDER BY product_price 
) 

Пример того, как таблицы выглядит следующим образом:

products: product_id, product_name 
products_inventory: inventory_id, product_id, product_price 
category_products: category_id, product_id 

Как просили, вот некоторые примерные данные:

products: 
1, lg tv 
2, samsung tv 

products_inventory 
1, 1, 500 
2, 1, 750 
3, 1, 800 
4, 2, 450 
5, 2, 600 

category_products 
1, 1 
1, 2 

На основе выборки данных вывод запроса должно быть: 450 - 500

+1

Вы проиндексировали поля, включенные в предложение WHERE? – opalenzuela

+0

IN с SELECT действительно плохая идея .... это как ORing сотни или миллион значений .... –

+0

Да, поля в индексе where все индексируются – Shiraz

ответ

1

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

Вы должны присоединиться к нему, что намного быстрее:

SELECT MIN(pi.product_price), MAX(pi.product_price) 
FROM products_inventory pi 
    JOIN products p ON p.product_id = pi.product_id 
    JOIN category_products cp ON cp.product_id = p.product_id 
WHERE cp.category_id IN (4,5,6,118) 
+0

Спасибо, вы запросили быстро, но он дает самую низкую и самую высокую цену для каждого product_id. То, что я пытаюсь достичь, является самой низкой и самой высокой ценой для всех продуктов, поэтому результат должен быть одним рядом. – Shiraz

+0

Хорошо, я неправильно понял :) –

+0

@ Rafal Ziolkowski этот вопрос прав, пожалуйста, проверьте мой скрипт sql. –

2

ОК, в первую очередь, я не вижу никакой разницы между вашим запросом и один ниже:

SELECT MIN(product_price), MAX(product_price) 
FROM products_inventory pi 
JOIN products p ON p.product_id = pi.product_id 
JOIN category_products cp ON cp.product_id = p.product_id 
WHERE cp.category_id IN (4,5,6,118) 
GROUP BY product_id 
ORDER BY product_price 

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

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

доверие Давайте вы и увеличить производительность, добавив индекс покрытия:

create index my_covering_index on products_inventory(product_id,product_price); 

Важным моментом в этом виде индексов использовать все от «где» п, то из «группы по» статье, а затем из предложения "select".

Обычно это должно быть достаточно, чтобы повысить свой запрос с Honda двигателем :)

+0

Также должен иметь индекс покрытия в таблице category_products (product_id, category_id) – DRapp

+0

не уверен, поскольку он не используется в предложении group by, и обычно категория представляет собой небольшую таблицу, что обычно означает, что она избежит использования индекса, поскольку она медленнее сканирования всей таблицы. По крайней мере, в Oracle это будет так. Если это большая таблица, то, couse, index будет полезен – smnbbrv

+0

снова есть contra: все пары значений уникальны, я думаю, и индекс в основном бесполезен. – smnbbrv

0

Ответ дается Рафал Зиолковски правильно, пожалуйста, проверьте SQL Fiddle для данных образцов и результатов запроса.

надеюсь, что это решит вашу проблему!

+0

Извините, похоже, я допустил ошибку в своем сообщении. Выход должен быть 450-500 вместо 450-800. Максимальное значение должно быть максимальным значением самого низкого значения всех продуктов – Shiraz

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