SELECT mo.*
FROM `client_money_operation` AS mo
LEFT JOIN `user` AS u ON mo.`user_id` = u.`id`
LEFT JOIN `client` AS c ON mo.`client_id` = c.`id`
LEFT JOIN `client_bonus_operation` AS bo ON mo.`id` = bo.`money_operation_id`
WHERE (mo.`status`=0)
AND (mo.`created_at` BETWEEN 1 AND 1539723600)
GROUP BY `operation_code`
ORDER BY `created_at` DESC
LIMIT 10
- довольно запутанное использование GROUP BY
.Во-первых, неправильно группировать по одному столбцу, имея много неагрегированных столбцов в списке SELECT
.И использование created_at
в ORDER BY
не имеет смысла, так как неясно, какая дата будет связана с каждым operation_code
.Возможно, вы хотите MIN(created_at)
?
Оптимизация ...
Будет выполнено полное сканирование mo
и (надеюсь) PRIMARY KEY
поиска в других таблицах.Пожалуйста, укажите EXPLAIN SELECT ...
, чтобы мы могли это проверить.
Единственный полезный индекс для mo
- это INDEX(status, created_at)
, и он может или не может быть полезен, в зависимости от того, насколько велик этот диапазон дат.
bo
нужен индекс, начинающийся с money_operation_id
.
В какие таблицы входят operation_code
и created_at
?Это имеет значение большое для оптимизатора.
Но есть шаблон, который, вероятно, можно использовать для значительного ускорения запроса.(Я не могу дать вам подробности, не зная, в какой таблице находятся эти столбцы, и нельзя ли заставить их работать.)
SELECT mo.*
FROM ( SELECT mo.id FROM .. WHERE .. GROUP BY .. ORDER BY .. LIMIT .. ) AS x
JOIN mo ON x.id = mo.id
ORDER BY .. -- yes, repeated
То есть first do (in aпроизводная таблица) минимальный работает, чтобы найти идентификаторы для 10 требуемых строк, затем используют JOIN (s), чтобы получить другие необходимые столбцы.
(Если yii2 не можетбыть создан, чтобы генерировать такие, тогда это мешает.)