Я пытаюсь выполнить запрос, который получит последние данные о времени, когда клиент разместил заказ. Проблема в том, что сайт позволяет людям оформлять заказы как в режиме входа, так и без него. Кроме того, я хочу объединить записи для клиентов, которые в какой-то момент изменили свой адрес электронной почты.
У меня есть работающий (я так думаю) запрос, но он включает три селекта – один для последнего заказа, один для переключений между вошедшими/выходящими пользователями и один для переключений электронной почты. Это довольно медленно в моей базе данных! Что я упускаю? Как я могу сделать этот запрос более эффективным и/или быстрым?
SELECT last, email, user_id
FROM (
SELECT last, email, user_id
FROM (
SELECT time as last, email,
CASE WHEN user_id > 0 THEN CAST(user_id as CHAR(20))
ELSE email
END as user_id
FROM orders o1
WHERE time=(SELECT MAX(o2.time)
FROM orders o2
WHERE o1.email = o2.email)
ORDER BY last DESC
) as o3
GROUP BY email
) as o4
GROUP BY user_id
ORDER BY email
Ответ
Чтобы оптимизировать ваш запрос в MariaDB, необходимо рассмотреть несколько аспектов, касающихся производительности и сложности выполнения запросов. Ваш текущий запрос использует вложенные подзапросы и операции GROUP BY, что может привести к снижению производительности, особенно при больших объемах данных.
Попробуем упростить и оптимизировать этот запрос. Ниже представлен оптимизированный вариант вашего запроса, который может помочь улучшить производительность:
SELECT
MAX(o.time) AS last,
CASE
WHEN MIN(o.user_id) > 0 THEN MIN(o.user_id)
ELSE MIN(o.email)
END AS identifier,
MIN(o.email) AS email
FROM
orders o
GROUP BY
COALESCE(CASE WHEN o.user_id > 0 THEN CAST(o.user_id AS CHAR(20)) ELSE o.email END, o.email)
ORDER BY
email;
Пояснение:
-
Составление запроса:
- Мы используем
MAX(o.time)
для получения последнего времени заказа для каждой записи без необходимости в подзапросах. - С помощью
MIN(o.user_id)
иMIN(o.email)
мы можем выбрать соответствующий идентификатор пользователя или email, который использовался в заказах.
- Мы используем
-
COALESCE и CASE:
- Мы используем оператор
COALESCE
, чтобы обработать идентификатор пользователя и email. Если пользователь авторизован (user_id > 0), то мы берем user_id, иначе – email.
- Мы используем оператор
- Группировка:
- Мы группируем только по преобразованному идентификатору (user_id или email), что позволяет сократить количество записей перед их обработкой, вместо того чтобы дважды выполнять группировку в подзапросах.
Дополнительные рекомендации:
-
Индексы:
- Убедитесь, что у вас есть индексы для столбцов
time
,email
, иuser_id
в таблицеorders
. Это может значительно увеличить скорость выполнения запросов.
- Убедитесь, что у вас есть индексы для столбцов
-
Анализ плана выполнения:
- Используйте команду
EXPLAIN
для анализа вашего запроса и получения понимания того, как создается план выполнения запроса. Это поможет вам выявить узкие места.
- Используйте команду
- Настройка сервера:
- Проверьте настройки вашего сервера MariaDB. В некоторых случаях оптимизация параметров конфигурации может привести к значительным улучшениям производительности.
Применив данные изменения, вы должны заметить увеличение скорости выполнения вашего запроса. Не забудьте протестировать его на ваших данных, чтобы убедиться в правильности и эффективности.