Я пытался найти эффективный способ разбить месяц данных щелчка в отдельные дни для графика, но большинство запросов, которые я собрал до сих пор, занимают 20-30 секунд, потому что у меня возникают проблемы думая о том, как сделать это без поддисков\подзапросов. Лучшее, что я придумал до сих пор:
SELECT
SUM(CASE WHEN ( TIME BETWEEN '2018/04/09' AND '2018/04/10') THEN 1 ELSE 0 END) 9th,
SUM(CASE WHEN ( TIME BETWEEN '2018/04/08' AND '2018/04/09') THEN 1 ELSE 0 END) 8th,
SUM(CASE WHEN ( TIME BETWEEN '2018/04/07' AND '2018/04/08') THEN 1 ELSE 0 END) 7th,
SUM(CASE WHEN ( TIME BETWEEN '2018/04/06' AND '2018/04/07') THEN 1 ELSE 0 END) 6th,
SUM(CASE WHEN ( TIME BETWEEN '2018/04/05' AND '2018/04/06') THEN 1 ELSE 0 END) 5th,
SUM(CASE WHEN ( TIME BETWEEN '2018/04/04' AND '2018/04/05') THEN 1 ELSE 0 END) 6th,
SUM(CASE WHEN ( TIME BETWEEN '2018/04/03' AND '2018/04/04') THEN 1 ELSE 0 END) 4th,
SUM(CASE WHEN ( TIME BETWEEN '2018/04/02' AND '2018/04/03') THEN 1 ELSE 0 END) 3rd
FROM
(
SELECT TIME, BIN_IP FROM CLICKS_IN WHERE USER_GROUP = 4 AND TIME BETWEEN '2018/04/02' AND '2018/04/10'
)a;
Объясните:
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE CLICKS_IN NULL ref USER_GROUP,TIME USER_GROUP 2 const 1614964 26.65 Using where
Или их вариации, но он все еще ужасно неэффективен с учетом потенциального количества записей (может потенциально получить 100k+ кликов в день). Также фактический код использует подготовленные заявления, поэтому не нужно указывать на это, я ставлю здесь значения для ясности.
Редактирование: я нашел, что следующее: -ло быстрее, но я обеспокоен тем, что он столкнется с проблемами, когда у меня будет больше групп пользователей в системе.
SELECT SUM(TIME >= '2018/04/09' AND TIME < '2018/04/10') as 9th,
SUM(TIME >= '2018/04/08' AND TIME < '2018/04/09') as 8th,
SUM(TIME >= '2018/04/06' AND TIME < '2018/04/08') as 7th,
SUM(TIME >= '2018/04/05' AND TIME < '2018/04/07') as 6th,
SUM(TIME >= '2018/04/04' AND TIME < '2018/04/06') as 5th,
SUM(TIME >= '2018/04/03' AND TIME < '2018/04/05') as 4th,
SUM(TIME >= '2018/04/02' AND TIME < '2018/04/04') as 3th
FROM CLICKS_IN USE INDEX (TIME)
WHERE TIME BETWEEN '2018/04/02' AND '2018/04/10'
AND USER_GROUP = 4
SELECT SUM(TIME >= '2018-04-09' AND TIME < '2018-04-10') as 9th,
SUM(TIME >= '2018-04-08' AND TIME < '2018-04-09') as 8th
FROM CLICKS_IN
WHERE USER_GROUP = 4
AND TIME >= '2018-04-02'
AND TIME < '2018-04-11'
И убедитесь, что у вас есть индексы во time
и столбцы user_group
. Затем он должен работать через несколько миллисекунд.
explain select ...
к вашему вопросу.
Вы можете сделать это, когда каждый день возвращается как строка. Построение его из строк в столбцы можно было бы сделать более эффективно в вызывающем PHP-коде.
SELECT
DAYOFMONTH(TIME) as 'day',
COUNT(*) as 'numclicks'
FROM 'CLICKS_IN'
WHERE USER_GROUP = 4 AND TIME BETWEEN '2018/04/02' AND '2018/04/10'
GROUP BY DAYOFMONTH(TIME)
ORDER BY DAYOFMONTH(TIME)
DAYOFMONTH()
не могут использовать индексы и работают очень медленно.
FROM ( SELECT TIME, BIN_IP FROM
на простоFROM
и удалите закрывающую псевдоним и производную таблицу с псевдонимом. И проверьте выводEXPLAIN
чтобы убедиться, что запрос использует соответствующий индексCLICKS_IN
таблицыCLICKS_IN
. Также обратите внимание, что время значения, которые находятся точно в полночь, будут включены в два сегмента, а не в одно.