AWS RDS MySql Простой запрос с составным индексом и диапазоном дат занял слишком много времени из ~ 8 миллионов данных - PullRequest
0 голосов
/ 16 апреля 2020

Запрос действительно прост, т.е.

SELECT 
    col1 , date_col 
FROM table USE INDEX (device_date_col) 
WHERE 
    device_id = "some_value"
    AND date_col BETWEEN "2020-03-16 00:00:00" and "2020-04-16 00:00:00" 
limit 1000000 ;

, но для окончательного возврата результата требуется 30–60 секунд, когда он запускается в первый раз. И тогда он возвращает результат менее чем за 10 секунд. И еще одна проблема заключается в том, что когда я меняю device_id, это снова занимает много времени. Я не могу понять, почему это происходит при использовании правильной индексации.

Мы знаем, что у шлюза API есть ограничение в 30 секунд из-за этого времени ожидания нашего API. Это происходит внезапно с сегодняшнего дня.

Основная цель - извлекать мелкие данные, он возвращает меньше данных, но также занимает много времени, т. Е.

 ....
 AND col1 IS NOT NULL
 GROUP BY 
    DATE(date_col),
    HOUR(date_col), 
    MINUTE(date_col)

Ниже приведена полезная информация

  1. AWS RDS с экземпляром db.m4.large (vCPU 2 и RAM 8 ГБ).
  2. MySql версия 5.6.x
  3. составной индекс для date_col и device_col
  4. с использованием InnoDB
  5. таблица не имеет поля идентификатора (первичный ключ)
  6. общее количество строк в таблице - 7,5 миллиона
  7. каждое устройство имеет данные каждые 3 секунды
  8. запросы возвращают строки вокруг 600k
  9. запрос объяснения показывает, что он использует индексирование
  10. List item

ОБНОВЛЕНИЕ

MySql Показы рабочей среды что, когда я запускаю запрос без группы, для его выполнения требуется 2 секунды, но для извлечения> 30 секунд, а когда я использую группу к тому времени, для выполнения сервера требуется> 30, а для извлечения - 2 секунды. Я думаю, нам нужно больше

  • Процессор для обработанных данных с использованием групп по
  • Больше оперативной памяти для извлечения всех данных ( без группировки по)

Ниже на рисунке показан ответ на запрос без группировки по. Посмотрите на продолжительность / время выборки

enter image description here

1 Ответ

0 голосов
/ 18 апреля 2020

(исходный запрос)

SELECT  col1 , date_col
    FROM  table USE INDEX (device_date_col)
    WHERE  device_id = "some_value"
      AND  date_col BETWEEN "2020-03-16 00:00:00"
                        AND "2020-04-16 00:00:00"
    limit  1000000 ;

Обсуждение INDEX(device_id, date_col, col1)

  1. Начать индекс с = столбца (-ов), имени, у device_id. Это несколько фокусирует поиск.
  2. В рамках этого, дальнейшее внимание уделяется диапазону дат. Итак, добавьте date_col к индексу. Теперь у вас есть оптимальный индекс для WHERE
  3. Тэка на все остальные столбцы, отображаемые в любом месте SELECT, если он не слишком много столбцов и не содержит TEXT столбцов. Теперь у вас есть индекс «покрытия». Это позволяет выполнять запрос, используя только индекс BTree, тем самым дополнительно увеличивая скорость.

Дополнительные обсуждения: http://mysql.rjweb.org/doc.php/index_cookbook_mysql

Другие примечания

  • LIMIT без ORDER BY обычно не имеет смысла - вы рискуете получить случайный набор строк.
  • Это BETWEEN включает дополнительную полночь. Я предлагаю

    AND  date_col >= "2020-03-16"
    AND  date_col  < "2020-03-16" + INTERVAL 1 MONTH
    
  • Удалите USE INDEX - Это может помочь сегодня, но может повредить завтра, когда изменятся данные или константы.

  • LIMIT 1000000 - Это может задушить некоторых клиентов. Тебе действительно нужно столько строк? Возможно, в базе данных можно было бы сделать больше обработки?
  • Добавление в GROUP BY - Может ли быть два значения для col1 в течение нескольких минут? Какое значение col1 вы получите? Рассмотрим MAX(col1), ANY_VALUE(col1) или GROUP_CONCAT(DISTINCT col1).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...