Повторяя комментарий от @Barmar, посмотрите на вывод EXPLAIN
, чтобы увидеть план выполнения запроса. Убедитесь, что используются подходящие индексы.
Вероятно, большой камень производительности - это операция "Использование сортировки файлов".
Чтобы обойти это, нам нужен подходящий доступный индекс. и это потребует некоторых изменений в таблице. (Типичный вопрос об «улучшении производительности запросов» topi c в SO имеет ограничения, которые мы «не можем добавлять индексы или вносить какие-либо изменения в таблицу».)
Я бы посмотрел функциональный индекс (функция добавлена в MySQL 8.0, для MySQL 5.7, я бы посмотрел на добавление сгенерированных столбцов и включение сгенерированных столбцов во вторичный индекс, функция добавлена в MySQL 5.7)
CREATE INDEX `MT4_TRADES_ix2` ON MT4_TRADES ((YEAR(close_time),MONTH(close_time))
Я бы соблазнился go с индексом покрытия, а также изменил бы группировку на одно выражение, например DATE_FORMAT(close_time,'%Y-%m')
CREATE INDEX `MT4_TRADES_ix3` ON MT4_TRADES ((DATE_FORMAT(close_time,'%Y-%m')
,swaps,volume,profit,login,cmd,closetime)
из запроса, похоже, что login
is будет УНИКАЛЬНЫМ в таблице MT4_USERS
, вероятно, это ПЕРВИЧНЫЙ КЛЮЧ или УНИКАЛЬНЫЙ КЛЮЧ, поэтому индекс будет доступен, но мы просто предполагаем ...
С подходящими доступными индексами мы может так что-то вроде этого:
SELECT DATE_FORMAT(close_time,'%Y-%m') AS close_year_mo
, SUM(IF(t.cmd < 2 AND t.close_time <> '1970-01-01', t.swaps ,NULL)) AS swaps
, SUM(IF(t.cmd < 2 AND t.close_time <> '1970-01-01', t.volume ,NULL))/100 AS volume
, SUM(IF(t.cmd < 2 AND t.close_time <> '1970-01-01', t.profit ,NULL)) AS profit
FROM MT4_TRADES t
JOIN MT4_USERS u
ON u.login = t.login
AND u.agent_account <> '1'
GROUP BY close_year_mo
ORDER BY close_year_mo
, и мы ожидаем, что MySQL выполнит свободное сканирование индекса, с выводом EXPLAIN
top show "использующий индекс для группировки", а не шоу " Использование сортировки файлов "
РЕДАКТИРОВАТЬ
* 10 29 * Для версий MySQL до 5.7 мы могли бы создать новые столбцы, например,
year_close
и
month_close
, заполнить столбцы результатами выражений
YEAR(close_time)
и
MONTH(close_time)
(мы могли бы создать BEFORE INSERT и BEFORE UPDATE запускает автоматическую обработку этого для нас)
Затем мы можем создать индекс с этими столбцами в качестве ведущих столбцов
CREATE INDEX ... ON MT4_TRADES ( year_close, month_close, ... )
И затем ссылаться на новые столбцы в запросе
SELECT t.year_close AS `YEAR`
, t.month_close AS `MONTH`
FROM MT4_TRADES t
JOIN ...
WHERE ...
GROUP
BY t.year_close
, t.month_close
В идеале включать в индекс все ссылочные столбцы из MT4_TRADES, чтобы покрывал индекс для запроса.