我们有一个查询,它在一个列上执行一些聚合。数据过滤似乎非常快,但是聚合似乎花费了太多时间。
此查询返回〜150万行。它运行0.6秒(如果我们想将数据返回给客户端,则需要2分钟左右的时间-我们通过使用pymysql python库进行测试)。我们使用了无缓冲游标,因此我们可以区分查询运行时间和获取时间):
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上聚合功能的这种可怕性能有任何帮助吗?为什么在150万行上计算Max Min和Avergae会花费这么长的时间(与相同数量的Python相比较,计算时间不到1秒。)
注意:我们为每个选择添加了随机数,以确保我们不会获取缓存的值。
我们使用Aurora RDS:1个db.r5.large实例(2 vCPU + 16 GB RAM)MySQL Engine版本: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
需要索引:
t_data: INDEX(period, to_date, label, val)
t_data: INDEX(period, label, to_date, val)
t_location_data: INDEX(period, country, to_date, id)
此外,从慢速IN ( SELECT ... )
更改为JOIN
:
FROM t_data AS d
JOIN t_location_data AS ld USING(id)
WHERE ...
还好,因为表格是1:1(是正确的吗?),请合并表格以消除JOIN
。如果id
不是每个表中的PRIMARY KEY
,则确实需要提供SHOW CREATE TABLE
并应更改名称。