Как я могу ускорить мой запрос MySQL (JOINs + GROUP BY) - PullRequest
0 голосов
/ 27 августа 2018

У меня есть этот запрос в mysql, и так как для его выполнения требуется почти 20 секунд, я хочу делать выборки из внутренних соединений с ограничениями, чтобы ускорить выполнение.

SELECT t1.order_id, CONCAT(t3.first_name,' ',t3.last_name),
    buyer_first_name, buyer_last_name, 
    max(product_quantity) as product_quantity, order_status, 
    order_value, t5.first_name staff_firstnamelogin, 
    t5.last_name staff_lastnamelogin, t6.day_name

FROM t_seller_order t0

INNER JOIN t_orders t1
                ON t0.event_id = t1.event_id 
               AND t1.seller_order_token = t0.seller_order_token

INNER JOIN t_tickets t2
                ON t1.order_id = t2.order_id

INNER JOIN t_login t3
                ON t3.login_id = t1.login_id

INNER JOIN t_login t5
                ON t0.login_id = t5.login_id

INNER JOIN t_event_days t6
                ON t2.product_id = t6.event_day_id

WHERE t0.event_id = 35

group by t1.order_id

order by order_id desc;

1 Ответ

0 голосов
/ 28 августа 2018

В схеме есть много вещей, которые мешают ускорению запроса. Посмотрим, что можно или нельзя сделать ...

Поскольку WHERE и GROUP BY попадают в разные таблицы, ни один индекс не полезен для обеих. Лучше всего иметь t0: INDEX(event_id).

Индексы для JOIN : t2..t6 нужны индексы (или PK) для order_id, login_id, event_day_id. t1 нужно INDEX(event_id, seller_order_token) в любом порядке.

GROUP BY и ORDER BY - это «одно и то же», поэтому будет использоваться только один вид, а не два.

Потенциальное ускорение - закончить GROUP BY до того, как выполнит часть JOINs. Текущей структурой является «inflate-deflate», где JOINs сговорились создать огромную временную таблицу, а затем GROUP BY дефлятирует результаты. Итак ...

Если посмотрите, можете ли вы написать SELECT, например:

SELECT t0.id, t1.id  -- I need the PRIMARY KEYs for these two tables
    FROM t_seller_order AS t0
    JOIN t_orders       AS t1
    WHERE t0.event_id = 35
    GROUP BY t1.order_id

Как быстро это? Надеемся, что мы сможем построить остальную часть запроса, но не слишком много времени. Есть два подхода; Я не знаю, что будет лучше.

План A: Использовать подзапросы (когда это возможно) вместо JOINs. Например, вместо JOINing to t3, plan on this being one item in the SELECT`:

    ( SELECT CONCAT(first_name,' ',last_name)
          FROM t_login WHERE login_id = t1.login_id
    ) AS login_name

(То же самое относится и к любым другим столбцам в SELECT, которые касаются таблицы только один раз. В нынешнем состоянии к t5 прикасаются дважды, поэтому такой подход может быть нецелесообразным.)

План Б: JOIN после GROUP BY. То есть после этого «спускают».

SELECT ...
    FROM ( SELECT t0.id, t1.id ... GROUP BY... ) AS x -- as discussed above
    JOIN y  ON y.foo = x.foo
    JOIN z  ON z.bar = x.bar
    -- the GROUP BY is avoided
    ORDER BY x.order_id desc;   -- The ORDER BY is still necessary

Ваш пример, я склоняюсь к Плану Б, но сочетание обоих «Планов» может быть желательным.

Дополнительные примечания: LEFT JOIN и LIMIT добавляют складки к приведенному выше обсуждению. Поскольку у вас их тоже не было, я не буду загромождать это обсуждение ими.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...