Почему этот запрос медленный в MySQL - PullRequest
0 голосов
/ 07 мая 2019

Я пытаюсь улучшить этот запрос, но мне это не удалось. Я использую некоторые левые соединения и подзапросы (я не знаю другой формы). Мы пытаемся получить все заказы от пользователей с определенным статусом и количеством заказов, кратными этому заказу, и получить от пользователя журнала происхождение. Запрос выполняется медленно, даже если используется ограничение limit. Я ценю всю помощь, которую вы можете оказать мне.

Это запрос:

SELECT DISTINCT b.uneaque_id, b.id, b.status, b.route_status, b.username, b.purpose, b.transfer, b.pickup_date, b.pickup_time, b.return_time, b.amount, b.default_location, b.start_address_route_comments, b.start_address_route, b.end_address_route_comments, b.end_address_route, u1.first_name, u1.last_name, b.transaction_Id, b.manual_payment, mr.AddressCount, lu.origin 
        FROM bookingdetails b 
        LEFT JOIN log_users lu ON lu.uneaque_id = b.uneaque_id AND lu.command_type = 'NEW BOOKING' 
        LEFT JOIN ( 
            SELECT booking_id, COUNT(*) AS AddressCount FROM booking_multiple_rides GROUP BY booking_id
        ) mr ON b.id = mr.booking_id,
        userdetails u1 WHERE b.username = u1.email 
        AND u1.user_status IN ('Active', 'Blocked', 'Not_Active')
        AND b.default_location = 1

PD: Извините за мой английский.

Ответы [ 2 ]

0 голосов
/ 10 мая 2019

Совет 1.

Скрытие производной таблицы в LEFT JOIN - рецепт медлительности.

Заменить

mr.AddressCount

на

( SELECT  COUNT(*)
            FROM  booking_multiple_rides
            WHERE booking_id = b.id
            GROUP BY  booking_id ) AS AddressCount

и избавьтесь от LEFT JOIN ( SELECT ... ) AS mr ON ..

Совет 2 Используйте явное JOINs, без старомодного «запятой-объединения»:

JOiN userdetails u1
    ON  b.username = u1.email

Это не поможетпроизводительность, но это прояснит ситуацию.

Совет 3: Если вам нужно INNER JOIN (u1) после LEFT JOIN, используйте скобки.Иначе, сначала поместите внутренние соединения, затем левые.Это облегчает использование, , но может испортить логику.

Совет 4: Не используйте LEFT, если вам это не нужно.Когда вам это не нужно, это сбивает с толку читателя (и оптимизатора).(Опять же, без изменений производительности.)

Совет 5: Почему вы используете DISTINCT?Для этого требуется дополнительный проход по всем наборам результатов.

Если они не помогают в достаточной степени, укажите SHOW CREATE TABLE, чтобы мы могли критиковать индексы.

0 голосов
/ 07 мая 2019

У вас есть ВКЛ b.id = mr.booking_id, userdetails u1 ГДЕ
Вы должны измениться с правильным внутренним соединением

SELECT DISTINCT b.uneaque_id
    , b.id, b.status
    , b.route_status
    , b.username
    , b.purpose
    , b.transfer
    , b.pickup_date
    , b.pickup_time
    , b.return_time
    , b.amount
    , b.default_location
    , b.start_address_route_comments
    , b.start_address_route
    , b.end_address_route_comments
    , b.end_address_route
    , u1.first_name
    , u1.last_name
    , b.transaction_Id
    , b.manual_payment
    , mr.AddressCount
    , lu.origin 
FROM bookingdetails b 
LEFT JOIN log_users lu ON lu.uneaque_id = b.uneaque_id AND lu.command_type = 'NEW BOOKING' 
LEFT JOIN ( 
        SELECT booking_id
          , COUNT(*) AS AddressCount 
          FROM booking_multiple_rides GROUP BY booking_id
) mr ON b.id = mr.booking_id
INNER JOIN userdetails u1 ON  b.username = u1.email 
AND u1.user_status IN ('Active', 'Blocked', 'Not_Active')
AND b.default_location = 1

и убедитесь, что у вас есть правильный индекс на
бронирование таблицы требует составного индекса по столбцам (uneaque_id, id, default_location)

таблица log_users составной индекс по столбцам (uneaque_id, command_type) Таблица user использует подробный индекс по столбцам (электронная почта, user_status)

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