Разбивая месяц на отдельные дни на большом столе

0

Я пытался найти эффективный способ разбить месяц данных щелчка в отдельные дни для графика, но большинство запросов, которые я собрал до сих пор, занимают 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
  • 0
    для лучшей производительности я бы не стал реализовывать производную таблицу. ... т.е. измените FROM ( SELECT TIME, BIN_IP FROM на просто FROM и удалите закрывающую псевдоним и производную таблицу с псевдонимом. И проверьте вывод EXPLAIN чтобы убедиться, что запрос использует соответствующий индекс CLICKS_IN таблицы CLICKS_IN . Также обратите внимание, что время значения, которые находятся точно в полночь, будут включены в два сегмента, а не в одно.
Теги:

2 ответа

0
Лучший ответ
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. Затем он должен работать через несколько миллисекунд.

  • 0
    У меня есть индексы для обоих, и этот запрос все еще составляет в среднем ~ 41 секунду. :
  • 0
    Пожалуйста, добавьте вывод explain select ... к вашему вопросу.
Показать ещё 5 комментариев
0

Вы можете сделать это, когда каждый день возвращается как строка. Построение его из строк в столбцы можно было бы сделать более эффективно в вызывающем 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)
  • 0
    Такие функции, как DAYOFMONTH() не могут использовать индексы и работают очень медленно.
  • 0
    Тогда не используйте функцию. Промежуток в where будет ограничивать возвращаемые строки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню