Предложение по использованию продуктов, связанных с MySQL InnoDB / PHP

#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; но иногда оптимизатор не может разобраться в этом, поэтому его работа далека от идеальной.