#mysql #query-optimization #innodb
#mysql #оптимизация запросов #innodb
Вопрос:
Я хочу расширить пользовательский интерфейс в моем магазине CodeIgniter предложениями о том, что другие люди купили с текущим продуктом (либо при просмотре продукта, либо когда продукт помещен в корзину, что сейчас не имеет значения для вопроса). Я придумал этот запрос (таблица orders содержит детали заказа, в то время как элементы заказа содержат продукты, которые расположены в определенном порядке с помощью внешнего ключа, псевдоним prd для таблицы products, где хранится вся важная информация о prduct). Запрос выглядит следующим образом
SELECT
pr.product_id,
COUNT(*) AS num,
prd.*
FROM
orders AS o
INNER JOIN order_items AS po ON o.id = po.order_id
INNER JOIN order_items AS pr ON o.id = pr.order_id
INNER JOIN products AS prd ON pr.product_id = prd.id
WHERE
po.product_id = '14211'
AND pr.product_id <> '14211'
GROUP BY
pr.product_id
ORDER BY
num DESC
LIMIT 3
Работает отлично, время запроса составляет 0,030 секунды, и он возвращает продукты, которые были куплены вместе с тем, который я просматриваю в данный момент.
Что касается вопросов и соображений, Percona query analyzer жалуется на эти две вещи, недетерминированную ГРУППИРОВКУ ПО и GROUP BY или ORDER BY в разных таблицах, которые оба мне нужны, чтобы я мог получать элементы сверху, которые действительно имеют отношение к соответствующему запросу, но абсолютно понятия не имею, как это исправить, или даже стоит ли мне действительно беспокоиться об этом уведомлении от query analyzer.
Второй вопрос касается производительности, поскольку для этого запроса он использует temporary и filesort, я думал о создании представления из этого запроса и использовать его вместо фактического выполнения запроса каждый раз, когда открывается какой-либо продукт.
Имейте в виду, что я не прошу советов по модели / представлению / контроллеру CI, просто советов о том, как оптимизировать этот запрос, и / или предложений относительно производительности и перехода к подходу views…
Любая помощь более чем приветствуется.
Комментарии:
1. Почему вы дважды объединяете order_items?
2. @krasipenkov первый, чтобы найти связь между элементом заказа и самим заказом, а второй, чтобы найти связь между выбранным элементом и элементами, существующими в заказах (или, по крайней мере, это то, что я имел в виду)
Ответ №1:
SELECT p.num, prd.*
FROM
(
SELECT a.product_id, COUNT(*) AS num
FROM orders AS o
INNER JOIN order_items AS b ON o.id = b.order_id
INNER JOIN order_items AS a ON o.id = a.order_id
WHERE b.product_id = '14211'
AND a.product_id <> '14211'
GROUP BY a.product_id
ORDER BY num DESC
LIMIT 3
) AS p
JOIN products AS prd ON p.product_id = prd.id
ORDER BY p.num DESC
Это должно
- Работайте быстрее (особенно по мере роста объема ваших данных),
- Избегайте группы по жалобе,
- не завышайте количество,
- и т. д
Игнорируйте жалобы на то, что GROUP BY
и ORDER BY
поступают из разных таблиц — это проблема с производительностью; вам это нужно.
Что касается перевода этого обратно в CodeIgniter, удачи.
Комментарии:
1. Боже мой, эта система комментариев… В любом случае, пожалуйста, исправьте псевдоним в последнем соединении, я думаю, вы имели в виду p.product_id = prd.id … Говоря о больших данных, считаете ли вы, что позже я должен перенести это на подход views?
2. Исправлено только что.
3. Я не думаю, что a
VIEW
не может быть быстрее, чем эквивалентSELECT
. Представление преобразуется в select; но иногда оптимизатор не может разобраться в этом, поэтому его работа далека от идеальной.