一、通过Presto insert到其他数据源的性能
1、压测结果
(K是一千,M是一百万)
源库 |
源表 |
行数 |
worker数 |
tpch -> hive |
tpch -> es6 |
tpch -> mysql |
|||
耗时(分:秒) |
速率(rows/s) |
耗时(分:秒) |
速率(rows/s) |
耗时(分:秒) |
速率(rows/s) |
||||
tiny |
lineitem |
60K |
4 |
1:57 |
513 |
||||
orders |
15K |
4 |
2:51 |
87 |
|||||
part |
2K |
4 |
2:34 |
12 |
|||||
supplier |
0.1K |
4 |
0:03 |
38 |
|||||
customer |
1.5K |
4 |
3:46 |
6 |
|||||
partsupp |
8K |
4 |
5:29 |
24 |
|||||
sf100 |
lineitem |
600M |
1 |
53:57 |
185K |
||||
4 |
13:28 |
743K |
871:13 |
11.5K |
400:10 |
25K |
|||
orders |
150M |
4 |
2:55 |
855K |
335:50 |
7.44K |
96:20 |
26K |
|
part |
20M |
4 |
0:41 |
485K |
52:12 |
6.38K |
11:18 |
29.5K |
|
supplier |
1M |
4 |
0:05 |
1050K |
0:27 |
36.8K |
0:38 |
26.3K |
|
customer |
15M |
1 |
3:21 |
74.4K |
|||||
4 |
0:25 |
610K |
25:27 |
9.82K |
9:49 |
25.5K |
|||
partsupp |
80M |
4 |
1:17 |
1050K |
211:57 |
6.29K |
43:36 |
30.6K |
|
sf300 |
lineitem |
1800M |
4 |
40:11 |
747K |
||||
orders |
450M |
4 |
8:03 |
932K |
|||||
part |
60M |
4 |
1:56 |
519K |
|||||
supplier |
3M |
4 |
0:06 |
483K |
|||||
customer |
45M |
4 |
1:11 |
634K |
|||||
partsupp |
240M |
4 |
3:28 |
1150K |
转换成图表如下所示(纵轴单位1000行/秒,横轴单位1百万行):
相同数据量不同数据源的insert速率
2、解读
随着worker数的增加,性能线性增长;
随着数据量的增加,耗时线性增长;
tpch -> hive 速度还是非常快的
tpch -> es6 慢很多,默认配置,未进行参数优化,查了下资料也无可优化写入的参数,由于速度非常慢,不建议大数据量插入。
tpch -> mysql 也不快,而且在insert时先将数据插入临时表,然后再从临时表导入到目标表,这样会消耗两倍的磁盘空间和时间,可使用create table as提高性能
3、建议
不建议使用Presto大批量insert数据到ElasticSearch或MySQL,在需要插数据到MySQL时要使用create table as
二、TPCH OLAP性能
1、TPCH介绍
TPC(事务处理性能委员会),由数十家会员公司创建的非盈利组织,功能是制定商务应用基准程序(Benchmark)的标准规范、性能和价格度量,并管理测试结果的发布,其发布的TPCH标准的主要目的是评价特定查询的决策支持能力,强调数据库在数据挖掘、分析处理方面的能力,包含22段复杂sql,详情可见https://yq.aliyun.com/articles/149715?t=t1
由于数据量的大小对查询速度有直接的影响,TPC- H 标准对数据库系统中的数据量有严格、明确的规定。用SF 描述数据量,1SF 对应1 GB 单位,SF 由低到高依次是1、10、30、100、300、1 000、3 000、10 000。需要强调,SF 规定的数据量只是8个基本表的数据量,不包括索引和临时表。
2、Hive和TPCH
(1)压测结果
无预热,以运行2次的平均时间作为最终运行时间,worker数4,每worker 100G内存
join_distribution_type为PARTITIONED,join_reordering_strategy为ELIMINATE_CROSS_JOINS
查询语句 |
sf100(基准的10000倍) |
sf300(基准的30000倍) |
sf1000(基准的100000倍) |
||||
HIVE on Presto |
Hive on MR |
TPCH on Presto |
HIVE on Presto |
Hive on MR |
TPCH on Presto |
TPCH on Presto |
|
q01 |
8.599 s ± 470.226 ms |
6.5 m |
8.779 s ± 337.290 ms |
14.363 s ± 173.241 ms |
12.5 m |
26.196 s ± 807.516 ms |
1.422 m ± 3.524 s |
q02 |
10.659 s ± 2.570 s |
>60 m 还未执行完 |
14.194 s ± 661.145 ms |
25.267 s ± 2.235 s |
>60 m 还未执行完 |
39.602 s ± 434.164 ms |
2.112 m ± 3.742 s |
q03 |
10.490 s ± 1.621 s |
8 m |
27.493 s ± 148.492 ms |
28.781 s ± 2.642 s |
11 m |
1.411 m ± 1.800 s |
4.813 m ± 2.956 s |
q04 |
4.152 s ± 57.276 ms |
6.5 m |
29.934 s ± 1.659 s |
10.121 s ± 827.315 ms |
6 m |
1.413 m ± 1.551 s |
4.997 m ± 5.850 s |
q05 |
19.645 s ± 2.247 s |
13 m |
32.882 s ± 510.531 ms |
59.886 s ± 4.129 s |
17.5 m |
1.591 m ± 1.481 s |
5.508 m ± 4.229 s |
q06 |
3.552 s ± 563.564 ms |
2 m |
4.158 s ± 1.613 s |
4.705 s ± 53.033 ms |
1.5 m |
13.544 s ± 1.587 s |
40.434 s ± 193.747 ms |
q07 |
30.973 s ± 1.561 s |
22 m |
47.387 s ± 921.360 ms |
1.545 m ± 1.936 s |
30 m |
2.227 m ± 4.816 s |
7.741 m ± 29.050 s |
q08 |
21.706 s ± 929.845 ms |
>90 m 还未执行完 |
38.677 s ± 147.785 ms |
1.125 m ± 826.608 ms |
>90 m 还未执行完 |
1.993 m ± 1.324 s |
4 worker,超过400G内存限制,资源不足 |
q09 |
30.347 s ± 1.276 s |
>60 m 还未执行完 |
59.550 s ± 996.313 ms |
1.599 m ± 5.453 s |
>60 m 还未执行完 |
2.998 m ± 3.964 s |
4 worker,超过400G内存限制,资源不足 |
q10 |
9.092 s ± 2.391 s |
13 m |
30.500 s ± 357.089 ms |
26.605 s ± 8.540 s |
12 m |
1.486 m ± 404.465 ms |
4.862 m ± 328.805 ms |
q11 |
7.166 s ± 322.441 ms |
7 m |
7.797 s ± 212.132 ms |
21.236 s ± 3.460 s |
10 m |
19.765 s ± 1.293 s |
58.372 s ± 8.522 s |
q12 |
4.087 s ± 171.827 ms |
7 m |
27.380 s ± 189.505 ms |
16.256 s ± 2.787 s |
9 m |
1.407 m ± 845.700 ms |
4.522 m ± 512.652 ms |
q13 |
9.660 s ± 622.961 ms |
5 m |
27.948 s ± 342.240 ms |
22.866 s ± 1.432 s |
10 m |
1.414 m ± 161.220 ms |
4.759 m ± 680.237 ms |
q14 |
4.084 s ± 324.562 ms |
4 m |
30.155 s ± 226.274 ms |
9.168 s ± 263.044 ms |
10 m |
1.514 m ± 303.349 ms |
5.025 m ± 439.113 ms |
q15 |
4.145 s ± 102.530 ms |
6 m |
7.805 s ± 398.101 ms |
10.273 s ± 128.693 ms |
21 m |
19.677 s ± 9.899 ms |
1.084 m ± 1.469 s |
q16 |
4.024 s ± 1.172 s |
8.5 m |
28.806 s ± 488.611 ms |
7.348 s ± 2.382 s |
24.5 m |
1.382 m ± 825.194 ms |
4.616 m ± 557.200 ms |
q17 |
25.625 s ± 1.013 s |
9 m |
36.223 s ± 511.238 ms |
1.252 m ± 613.062 ms |
33 m |
1.898 m ± 450.427 ms |
6.265 m ± 127.279 ms |
q18 |
24.291 s ± 917.825 ms |
20.5 m |
42.352 s ± 132.229 ms |
1.375 m ± 5.720 s |
50 m |
2.239 m ± 1.923 s |
7.535 m ± 2.703 s |
q19 |
4.456 s ± 737.512 ms |
13 m |
32.079 s ± 828.022 ms |
13.788 s ± 1.279 s |
80 m |
1.588 m ± 485.782 ms |
5.250 m ± 1.347 s |
q20 |
7.854 s ± 2.233 s |
4.5 m |
33.239 s ± 598.212 ms |
21.219 s ± 3.412 s |
34.5 m |
1.657 m ± 183.141 ms |
5.460 m ± 1.004 s |
q21 |
58.191 s ± 5.942 s |
18.5 m |
1.072 m ± 1.531 s |
2.648 m ± 2.150 s |
83 m |
3.305 m ± 7.362 s |
4 worker,超过400G内存限制,资源不足 |
q22 |
3.363 s ± 1.896 s |
1.5 m |
25.634 s ± 730.441 ms |
6.997 s ± 1.295 s |
2 m |
1.245 m ± 3.536 ms |
4.184 m ± 801.859 ms |
转换成图表后如下所示(纵轴单位是秒):
同一数据量下的比较
不同数据量TPCH on Presto的表现:
(2)解读
随着worker数的增加,性能线性增长;
随着数据量的增加,耗时低于线性增长,对于批量处理的优化还是比较高的;
当Hive由MR引擎更换到Presto引擎后,性能提升是显著的,可以将原来小时级的任务加速到秒级;
由于插入数据是比较耗时的,所以又测了TPCH数据源的性能,这个数据源支持最高达300万倍基准数据的庞大数据量测试,通过比较发现,
HIVE on Presto比同数据量的TPCH on Presto执行要快,可能是因为Hive数据存的是分布式文件系统Hdfs,且文件格式是列式存储ORC,读取效率高
因此可通过TPCH on Presto大致估算HIVE on Presto执行所需的最大时长,发现4节点400G的Presto是完全可以支撑3万倍基准数据的OLAP查询的,可以支撑大部分的10万倍基准数据的复杂查询,有3个10万倍基准数据的复杂查询由于内存资源不足无法支撑
(3)建议
在内存资源足够的情况下,建议使用Presto作为Hive的执行引擎
3、ElasticSearch
(1)压测结果
由于ES on Presto并不完全支持sql语法,如对一个字符串类型的列进行过滤时,使用Presto where过滤只能得到空值,需要用Presto ES connector的push-down特性才可以得到正确结果,而TPCH的sql非常复杂,且实际使用ES的场景中很少需要用到这么复杂的查询,因此只针对少量常用语法进行比较
索引数据量 |
操作 |
ES on Presto |
ES on DSL |
||
tiny_customer |
数据量 |
select count(1) from es6.default.tinyconsumer; |
1s |
GET /tiny_customer/_search |
1s |
使用_dsl强下推 |
1s |
||||
简单过滤字段 |
注意对于文本数据,必须使用push-down特性,不然查不到数据 |
1s |
GET /tiny_customer/_search |
2s |
|
select count(1) from customer where _mktsegment=match_phrase('HOUSEHOLD'); |
1s |
||||
去重数据量 |
select count(distinct nationkey) from tiny_customer; |
1s |
GET /tiny_customer/_search |
1s |
|
customer |
数据量 |
select count(1) from es6.default.consumer; |
610s |
GET /customer/_search |
1s |
使用_dsl强下推 |
600s |
||||
简单过滤字段 |
注意对于文本数据,必须使用push-down特性,不然查不到数据 |
2s |
GET /customer/_search |
2s |
|
select count(1) from customer where _mktsegment=match_phrase('HOUSEHOLD'); |
140s |
||||
去重数据量 |
select count(distinct nationkey) from customer; |
630s |
GET /customer/_search |
1s |
(2)解读
若查的数据量不大,Presto性能还是可以的,且更方便易用,但对于大数据量,发现只是查数据子集时两者性能差别不大,但遇到需要查数据量等扫描全索引的情况,这个时候ES on Presto就远不如ES on ES快,因为ES本身有丰富的统计信息,且对查询做了很多优化,而Presto需要把所有数据查出来再进行统计,即使使用_dsl强下推也无法显著提高性能,看来Presto并未针对ES特性做足够的优化
(3)建议
索引数据量不大的场景,或对性能不敏感且对易用性敏感的场景,可以使用Presto查ES中的数据。但在查询时注意不能完全套用普通sql语法,要对语法做充分测试
三、性能优化
1、数据源优化
Presto使用的是MPP架构,使用纯内存计算,计算的效率是很高的,但在计算前要先把数据从数据源中读出来,这个阶段的性能就非常取决于数据源。
当在Presto上对数据库跨库查询,例如Mysql数据库。这个时候Presto的做法是从MySQL数据库端拉取最基本的数据,然后再去做进一步的处理,例如统计等聚合操作。
举个栗子:
SELECT count(id) FROM table_1 WHERE condition=1;
上面的SQL语句会分为3个步骤进行:
- Presto发起到Mysql数据库进行查询
SELECT id FROM table_1 WHERE condition=1;
- 对结果进行count计算
- 返回结果
所以说,对于Presto来说,其跨库查询的瓶颈是在数据拉取这个步骤。当一个查询中有多个数据源时,瓶颈取决于最慢的数据源的读取效率,当查询性能无法满足要求时,可考虑使用Presto sql把Mysql中相关的数据表定期转移到HDFS中,并转存为高效的列式存储格式ORC,且在归档的时候我们要选择一个归档字段,如果是按日归档,我们可以用日期作为这个字段的值,采用yyyy-MM-dd的形式,例如2019-01-23。
2、集群优化
(1)加节点数比加内存性能提升更明显,因为加节点不光会加内存,还会加cpu,提高处理能力
(2)当内存不足,经常发生GC会极大降低性能甚至导致查询失败
(3)单个节点的内存设置不可过小
因为有的聚合运算的reduce步骤只能放在同一台机器执行,这个时候若内存数过小,会发生大量GC降低性能,甚至OOM无法执行。这是tpch q08,一个8表的join、group by操作,在一个130G的集群上执行,每个节点24G内存,但经过短时间的100多G内存的占用后持续了较长时间的24G内存占用,就是这个原因。一共需要执行12分钟,只有3分钟是占用了100多G内存
四、业界压测参考
以上内容只做了关于Presto的纵向性能测试,业界有做了关于市面上流行的开源引擎的比较,有兴趣的可以看看
开源OLAP引擎测评报告(SparkSql、Presto、Impala、HAWQ、ClickHouse、GreenPlum)