У нас есть запрос, который выполняет некоторое агрегирование по одному столбцу. Фильтрация данных кажется довольно быстрой, но агрегация занимает слишком много времени.
Этот запрос возвращает ~ 1,5 миллиона строк. Он работает в течение 0,6 секунд (если мы хотим вернуть данные клиенту, это займет ~ 2 минуты - способ, которым мы протестировали это с помощью библиотеки py mysql python. Мы использовали небуферизованную курсор, поэтому мы можем различить guish между временем выполнения запроса и временем выборки):
SELECT *
FROM t_data t1
WHERE (t1.to_date = '2019-03-20')
AND (t1.period = 30)
AND (label IN ('aa','bb') )
AND ( id IN (
SELECT id
FROM t_location_data
WHERE (to_date = '2019-03-20') AND (period = 30)
AND ( country = 'Narniya' ) ) )
Но если мы запустим этот запрос:
SELECT MAX(val) val_max,
AVG(val) val_avg,
MIN(val) val_min
FROM t_data t1
WHERE (t1.to_date = '2019-03-20')
AND (t1.period = 30)
AND (label IN ('aa','bb') )
AND ( id IN (
SELECT id
FROM t_location_data
WHERE (to_date = '2019-03-20') AND (period = 30)
AND ( country = 'Narniya' ) ) )
Мы увидим, что время выполнения запроса занимает 40 секунд, а время получения результатов в этом случае, очевидно, меньше секунды.
Помогите ли вы с этой ужасной производительностью функций агрегирования над RDS Aurora? Почему вычисление Max Min и Avergae на 1,5 миллиона строк занимает так много времени (при сравнении с Python для тех же чисел вычисление занимает менее 1 секунды ..)
ПРИМЕЧАНИЕ. Мы добавили случайное число к каждому выбору чтобы убедиться, что мы не получаем кэшированные значения.
Мы используем Aurora RDS:
1 экземпляр db.r5.large (2 vCPU + 16 ГБ ОЗУ) MySQL Версия двигателя: 5.6 .10a
Создать таблицу:
Create Table: CREATE TABLE `t_data` (
`id` varchar(256) DEFAULT NULL,
`val2` int(11) DEFAULT NULL,
`val3` int(11) DEFAULT NULL,
`val` int(11) DEFAULT NULL,
`val4` int(11) DEFAULT NULL,
`tags` varchar(256) DEFAULT NULL,
`val7` int(11) DEFAULT NULL,
`label` varchar(32) DEFAULT NULL,
`val5` varchar(64) DEFAULT NULL,
`val6` int(11) DEFAULT NULL,
`period` int(11) DEFAULT NULL,
`to_date` varchar(64) DEFAULT NULL,
`data_line_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`data_line_id`),
UNIQUE KEY `id_data` (`to_date`,`period`,`id`),
KEY `index1` (`to_date`,`period`,`id`),
KEY `index3` (`to_date`,`period`,`label`)
) ENGINE=InnoDB AUTO_INCREMENT=218620560 DEFAULT CHARSET=latin1
Create Table: CREATE TABLE `t_location_data` (
`id` varchar(256) DEFAULT NULL,
`country` varchar(256) DEFAULT NULL,
`state` varchar(256) DEFAULT NULL,
`city` varchar(256) DEFAULT NULL,
`latitude` float DEFAULT NULL,
`longitude` float DEFAULT NULL,
`val8` int(11) DEFAULT NULL,
`val9` tinyint(1) DEFAULT NULL,
`period` int(11) DEFAULT NULL,
`to_date` varchar(64) DEFAULT NULL,
`location_line_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`location_line_id`),
UNIQUE KEY `id_location_data` (`to_date`,`period`,`id`,`latitude`,`longitude`),
KEY `index1` (`to_date`,`period`,`id`,`country`),
KEY `index2` (`country`,`state`,`city`),
KEY `index3` (`to_date`,`period`,`country`,`state`)
) ENGINE=InnoDB AUTO_INCREMENT=315944737 DEFAULT CHARSET=latin1
Параметры:
@@innodb_buffer_pool_size/1024/1024/1024: 7.7900
@@innodb_buffer_pool_instances: 8
ОБНОВЛЕНИЕ: Добавление индекса val
(например, Предложение @ rick-james) значительно улучшило запрос (заняло ~ 2 секунды) , только если я удалил условие AND ( id IN (SELECT id FROM t_location_data..
. Если я оставлю его, запрос будет выполняться примерно на ~ 25 секунд ... лучше, чем раньше, но все еще не хорошо ..