Оптимизация запросов MariaDB при повторном обращении к одной и той же таблице

Вопросы и ответы

Я пытаюсь выполнить запрос, который получит последние данные о времени, когда клиент разместил заказ. Проблема в том, что сайт позволяет людям оформлять заказы как в режиме входа, так и без него. Кроме того, я хочу объединить записи для клиентов, которые в какой-то момент изменили свой адрес электронной почты.

У меня есть работающий (я так думаю) запрос, но он включает три селекта – один для последнего заказа, один для переключений между вошедшими/выходящими пользователями и один для переключений электронной почты. Это довольно медленно в моей базе данных! Что я упускаю? Как я могу сделать этот запрос более эффективным и/или быстрым?

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;

Пояснение:

  1. Составление запроса:

    • Мы используем MAX(o.time) для получения последнего времени заказа для каждой записи без необходимости в подзапросах.
    • С помощью MIN(o.user_id) и MIN(o.email) мы можем выбрать соответствующий идентификатор пользователя или email, который использовался в заказах.
  2. COALESCE и CASE:

    • Мы используем оператор COALESCE, чтобы обработать идентификатор пользователя и email. Если пользователь авторизован (user_id > 0), то мы берем user_id, иначе – email.
  3. Группировка:
    • Мы группируем только по преобразованному идентификатору (user_id или email), что позволяет сократить количество записей перед их обработкой, вместо того чтобы дважды выполнять группировку в подзапросах.

Дополнительные рекомендации:

  1. Индексы:

    • Убедитесь, что у вас есть индексы для столбцов time, email, и user_id в таблице orders. Это может значительно увеличить скорость выполнения запросов.
  2. Анализ плана выполнения:

    • Используйте команду EXPLAIN для анализа вашего запроса и получения понимания того, как создается план выполнения запроса. Это поможет вам выявить узкие места.
  3. Настройка сервера:
    • Проверьте настройки вашего сервера MariaDB. В некоторых случаях оптимизация параметров конфигурации может привести к значительным улучшениям производительности.

Применив данные изменения, вы должны заметить увеличение скорости выполнения вашего запроса. Не забудьте протестировать его на ваших данных, чтобы убедиться в правильности и эффективности.

Оцените материал
Добавить комментарий

Капча загружается...