Я генерирую CSV из числа заказов, которые я получаю каждый месяц за последние 12 месяцев на единицу. В данный момент я извлекаю элементы и использую цикл foreach, чтобы отправить следующий запрос для каждого элемента, чтобы получить общее количество заказов, которое было заказано в каждом месяце за последние 12 месяцев. Однако запрос занимает чуть более 3 секунд, поэтому, когда цикл повторяется несколько тысяч раз, сервер MySQL отключается.
Как я могу оптимизировать этот запрос? Следует ли уменьшить нагрузку на базу данных, если вместо этого я использую подзапрос?
Вот запрос (который был адаптирован из Вот):
SELECT order_item_variant_alias_id, DATE(DATE_FORMAT(order_progress_time, '%Y-%m-01')) AS `trueMonth`, COUNT(*) AS count
FROM tbl_order_progress
JOIN tbl_order_items ON order_progress_order_id = order_item_order_id
JOIN tbl_product_variant_aliases ON order_item_variant_alias_id = product_variant_alias_id
JOIN tbl_product_variants ON product_variant_id = product_variant_alias_variant_id
GROUP BY product_variant_alias_id, DATE(DATE_FORMAT(order_progress_time, '%Y-%m-01'))
HAVING order_item_variant_alias_id = 1
Почему вы запускаете отдельный запрос для каждого элемента? Просто бросьте having
пункт и положить все предметы в то же время.
Если по какой-то причине вам нужно делать по одному элементу за раз, переключите логику на where
пункт, а не having
пункт. having
пункт будет агрегировать все элементы, а затем отфильтровать до того, который вы хотите. MySQL должен быть быстрее, если вы сначала уменьшите данные — используя where
:
SELECT order_item_variant_alias_id,
DATE(DATE_FORMAT(order_progress_time, '%Y-%m-01')) AS `trueMonth`,
COUNT(*) AS count
FROM tbl_order_progress JOIN
tbl_order_items
ON order_progress_order_id = order_item_order_id JOIN
tbl_product_variant_aliases
ON order_item_variant_alias_id = product_variant_alias_id JOIN
tbl_product_variants
ON product_variant_id = product_variant_alias_variant_id
WHERE order_item_variant_alias_id = 1
GROUP BY product_variant_alias_id,
DATE(DATE_FORMAT(order_progress_time, '%Y-%m-01'));
Других решений пока нет …