@xiiicool

Почему запрос с count долго выполняется?

база mysql 8 движок InnoDb, поле fileDate тип date, партиции на каждый день, индекс на fileDate стоит
запрос
SELECT cdrs.fileDate, count(*)
FROM billing_api.cdrs
WHERE fileDate >= '2024-03-18'
  AND fileDate <= '2024-03-24'
GROUP BY fileDate;


время выполнения без count 100ms с count 1 минута 50 сек

результат explain
1, 'SIMPLE', 'cdrs', '...', 'range', 'fileDate', 'fileDate', '3', null, 46678961, 100, 'Using where; Using index'
результат EXPLAIN analyze
-> Group aggregate: count(0)  (cost=14066345.63 rows=46678961) (actual time=19262.629..117008.029 rows=7 loops=1)
    -> Filter: ((cdrs.fileDate >= DATE'2024-03-18') and (cdrs.fileDate <= DATE'2024-03-24'))  (cost=9398449.53 rows=46678961) (actual time=1.198..108947.804 rows=97238448 loops=1)
        -> Covering index range scan on cdrs using fileDate over ('2024-03-18' <= fileDate <= '2024-03-24')  (cost=9398449.53 rows=46678961) (actual time=1.195..92245.365 rows=97238448 loops=1)
  • Вопрос задан
  • 3206 просмотров
Пригласить эксперта
Ответы на вопрос 7
tkovacs
@tkovacs
веб мастер
Потому что идёт подсчет количества записей, по этой же причине на многих сайтах отсутствует пагинация с номерами страниц, только вперёд и назад или подгрузка записей
Ответ написан
@Hlapchynya
Попробуй заменить count(") на сount(1)
Ответ написан
@Ambulate
Сделай подзапрос, и поверх него сеэделай каунт
Ответ написан
Комментировать
@Medicavt
Там же индекс по полю группировки. Без count выводится просто distinct от фильтра по индексу, все миллионы записей не поднимаются с диска. А с count надо поднять все фильтрованные записи и посчитать кол-во для каждой уникальной даты.
Ответ написан
Комментировать
@coodi
Можно сделать индекс по датам?
Ответ написан
Комментировать
Tpona
@Tpona
Ужасный перфекционист
Как на счет

select count(t.fileDate) cnt, t.fileDate 
from (select cdrs.fileDate from cdrs.fileDate 
where fileDate >= '2023-03-18'
  and fileDate <= '2024-03-24'
) as t
group by fileDate;


То есть сначала фильтруем, потом группируем. Мне видится так должно работать оптимальнее.
Ответ написан
Revencu
@Revencu
Не пробовали использовать SQL_CALC_FOUND_ROWS?
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы