У меня есть запрос mysql, который занимает 30 секунд. в таблице содержится более 3 миллионов строк
вот структура db:
text (VARCHAR(64)),
kpi1 (INT),
kpi2 (INT),
position (DECIMAL),
date(DATE)
device (VARCHAR(32))
Вот запрос:
select date, sum(kpi1), sum(kpi2) FROM 'table_name' GROUP BY date ;
Объяснить метод дает мне этот результат:
ID | select type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtred | extra
1 | SIMPLE | table_name | NULL | index | UNIQUE,DATE | DATE | 3 | NULL | 3316480 | 100.00 | NULL
У меня есть указатель на дату.
Здесь результат с профилированием:
mysql> show profile for query 1;
+----------------------+-----------+
| Status | Duration |
+----------------------+-----------+
| starting | 0.000080 |
| checking permissions | 0.000011 |
| Opening tables | 0.000021 |
| init | 0.000023 |
| System lock | 0.000011 |
| optimizing | 0.000007 |
| statistics | 0.000021 |
| preparing | 0.000019 |
| Sorting result | 0.000007 |
| executing | 0.000005 |
| Sending data | 32.814836 |
| end | 0.000011 |
| query end | 0.000009 |
| closing tables | 0.000009 |
| freeing items | 0.000082 |
| cleaning up | 0.000013 |
+----------------------+-----------+
16 rows in set, 1 warning (0,00 sec)
Любая идея?
Если данные по историческим датам статичны (как, например, не изменяются, поскольку дата/активность уже выполнена), то это прекрасный пример того, когда использовать сводную таблицу. Создайте отдельную таблицу, которая представляет собой ни что иное, как дату и агрегаты по мере необходимости. Сделайте это за все дни до текущего, так что только в конце дня вы вставляете (например, какой-то суточный триггер) сумму предыдущего дня. Вы даже можете включить количество записей, что-то вроде
insert into MyDailySummaryTable
( Date, kpi1Sum, kpi2Sum, numRecs )
select date,
sum(kpi1) kpi1Sum,
sum(kpi2) kpi2Sum,
count(*) numRecs
FROM
'table_name'
where
date < curdate()
GROUP BY
date ;
затем на каждый день после начальной загрузки
insert into MyDailySummaryTable
( Date, kpi1Sum, kpi2Sum, numRecs )
select date,
sum(kpi1) kpi1Sum,
sum(kpi2) kpi2Sum,
count(*) numRecs
FROM
'table_name'
where
date = date_add( curdate(), interval -1 day )
GROUP BY
date ;
Если в поле "дата" также есть информация о временной отметке, вам может потребоваться отрегулировать запрос, чтобы игнорировать временные порции.
Затем, пытаясь запустить ваши итоги, вы можете просто запросить у MyDailySummaryTable напрямую и получить мгновенные результаты.
Вы даже можете расширить таблицу агрегирования запросов, чтобы включить подсчеты на устройство в случае, если вы когда-либо захотели найти информацию отслеживания для этого конкретного устройства.
(date, kpi1, kpi2)