@alexmixaylov

Почему запрос в базу выполняется больше 15 минут?

В магазине на престашопе очень дого начала загружаться страница заказчиков
при детальном рассмотрении выяснилось что проблема в медленном ответе базы.
Запрос на получение 50 строк с несколькими подзапросами может выполняться до 30 минут
Включил профилирование, выяснил, что львиную долю времени отжирает запрос в базу
Скопировав и выполнив SQL запрос в консоли - получил то же время
Получается что проблема не в скрипте, а в работе базы данных

сам запрос выглядит таким образом
SELECT SQL_NO_CACHE a.`id_customer`,
                    `firstname`,
                    `lastname`,
                    `email`,
                    a.`active` AS `active`,
                    `newsletter`,
                    `optin`
        ,
                    a.date_add,
                    gl.name    as title,
                    (
                        SELECT SUM(total_paid_real / conversion_rate)
                        FROM ps_orders o
                        WHERE o.id_customer = a.id_customer
                          AND o.id_shop IN (1)
                          AND o.valid = 1
                    )          as total_spent,
                    (
                        SELECT c.date_add
                        FROM ps_guest g
                                 LEFT JOIN ps_connections c ON c.id_guest = g.id_guest
                        WHERE g.id_customer = a.id_customer
                        ORDER BY c.date_add DESC
                        LIMIT 1
                    )          as connect
FROM `ps_customer` a
         LEFT JOIN ps_gender_lang gl ON (a.id_gender = gl.id_gender AND gl.id_lang = 1)
WHERE 1
  AND a.`deleted` = 0
ORDER BY `date_add` DESC
LIMIT 0, 50

я включил логгирование медленных запросов
но там ничто не вызывает подозрения
# Query_time: 0.000470  Lock_time: 0.000154  Rows_sent: 1  Rows_examined: 3
# Query_time: 0.000520  Lock_time: 0.000119  Rows_sent: 1  Rows_examined: 4
# Query_time: 0.002848  Lock_time: 0.000083  Rows_sent: 849  Rows_examined: 864
# Query_time: 0.000613  Lock_time: 0.000199  Rows_sent: 1  Rows_examined: 3
# Query_time: 0.000687  Lock_time: 0.000154  Rows_sent: 1  Rows_examined: 4
# Query_time: 0.005767  Lock_time: 0.000113  Rows_sent: 849  Rows_examined: 864
# Query_time: 0.000467  Lock_time: 0.000149  Rows_sent: 1  Rows_examined: 3
# Query_time: 0.000497  Lock_time: 0.000112  Rows_sent: 1  Rows_examined: 4
# Query_time: 0.009653  Lock_time: 0.006193  Rows_sent: 849  Rows_examined: 864
# Query_time: 0.000448  Lock_time: 0.000142  Rows_sent: 1  Rows_examined: 3
# Query_time: 0.000734  Lock_time: 0.000177  Rows_sent: 1  Rows_examined: 4
# Query_time: 0.005696  Lock_time: 0.000115  Rows_sent: 849  Rows_examined: 864

получается что тормоза возникают между запросами
что это моголо бы быть и как это можно отследить, не пойму
получаю результат запроса в консоли 50 rows in set (17 min 24.94 sec)
  • Вопрос задан
  • 138 просмотров
Решения вопроса 1
@Zolg
Ну так и спросите об этом саму базу:
https://dev.mysql.com/doc/refman/5.5/en/explain.html
Wb умеет и диаграмки строить
https://dev.mysql.com/doc/workbench/en/wb-performa...
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@dimoff66
Кратко о себе: Я есть
Честно говоря первый раз вижу подобный подзапрос, используемый в селект, полагаю он должен отрабатывать для каждой строки отдельно и являться причиной тормозов с ростом базы. Возможно и с индексацией полей траблы.

(
                        SELECT SUM(total_paid_real / conversion_rate)
                        FROM ps_orders o
                        WHERE o.id_customer = a.id_customer
                          AND o.id_shop IN (1)
                          AND o.valid = 1
                    )          as total_spent,


Попробуйте сначала перенести таблицу для этого поля в раздел FROM и потом уже соединять с таблицей a

SELECT SQL_NO_CACHE a.`id_customer`,
                    `firstname`,
                    `lastname`,
                    `email`,
                    a.`active` AS `active`,
                    `newsletter`,
                    `optin`,
                    a.date_add,
                    gl.name    as title,
                    total_spents.total_spent
FROM `ps_customer` a
         LEFT JOIN ps_gender_lang gl ON (a.id_gender = gl.id_gender AND gl.id_lang = 1)
         LEFT JOIN (
                        SELECT o.id_customer, SUM(total_paid_real / conversion_rate) as total_spent
                        FROM ps_orders o
                        WHERE o.id_customer IN (SELECT id_customer FROM `ps_customer` a WHERE a.deleted = 0)
                          AND o.id_shop IN (1)
                          AND o.valid = 1
                       GROUP BY o.id_customer
                    )     total_spents ON a.id_customer = total_spents.id_customer,
WHERE 1
  AND a.`deleted` = 0
ORDER BY `date_add` DESC
LIMIT 0, 50


То же самое и с другим подобным полем
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы