Presto是Facebook开源的MPP(Massive Parallel Processing)SQL引擎,其理念来源于一个叫Volcano的并行数据库,该数据库提出了一个并行执行SQL的模型,它被设计为用来专门进行高速、实时的数据分析。Presto是一个SQL计算引擎,分离计算层和存储层,其不存储数据,通过Connector SPI实现对各种数据源(Storage)的访问。Presto沿用了通用的Master-Slave架构,一个Coordinator,多个Worker。Coordinator负责解析SQL语句,生成执行计划,分发执行任务给Worker节点执行,Worker节点负责实际执行查询任务。Presto提供了一套Connector接口,用于读取元信息和原始数据。Presto 内置有多种数据源,如 Hive、MySQL、Kudu、Kafka 等。Presto 的扩展机制允许自定义 Connector,从而实现对定制数据源的查询。假如配置了Hive Connector,需要配置一个Hive MetaStore服务为Presto提供Hive元信息,Worker节点通过Hive Connector与HDFS交互,读取原始数据。Presto是一个交互式查询引擎,我们关心的是Presto实现低延时查询的原理,以下几点是其性能脱颖而出的主要原因:与Hive类似,Presto会根据元信息读取分区数据,合理的分区能减少Presto数据读取量,提升查询性能。Presto对ORC文件读取做了特定优化,因此在Hive中创建Presto使用的表时,建议采用ORC格式存储。相对于Parquet,Presto对ORC支持更好。数据压缩可以减少节点间数据传输对IO带宽压力,对于即席查询需要快速解压,建议采用snappy压缩有条件的话提前做好排序,对于已经排序的数据,在查询的数据过滤阶段,ORC格式支持跳过读取不必要的数据。① select时只选择必要字段,避免使用 * 号③ 合理安排Group by语句中字段顺序对性能有一定提升将Group By语句中字段按照每个字段distinct数据多少进行降序排列。示例中uid是用户id,比性别数据大很多。[GOOD]: SELECT GROUP BY uid, gender
[BAD]: SELECT GROUP BY gender, uid
Order by需要扫描数据到单个worker节点进行排序,导致单个worker需要大量内存。如果是查询Top N或者Bottom N,使用limit可减少排序计算和内存压力。Presto查询优化器没有对多个like语句进行优化,使用regexp_like对性能有较大提升[GOOD]
SELECT ...
FROM access
WHERE regexp_like(method, 'GET|POST|PUT|DELETE')
[BAD]
SELECT ...
FROM access
WHERE
method LIKE '%GET%' OR
method LIKE '%POST%' OR
method LIKE '%PUT%' OR
method LIKE '%DELETE%'
⑥ 使用Rank函数代替row_number函数来获取Top N在进行一些分组排序场景时,使用rank函数性能更好Presto中join的默认算法是broadcast join,即将join左边的表分割到多个worker,然后将join右边的表数据整个复制一份发送到每个worker进行计算。1)修改配置distributed-joins-enabled (presto version >=0.196)2)在每次查询开始使用distributed_join的session选项set session distributed_join = 'true'
SELECT ...
FROM
large_table1
join large_table2
on large_table1.id = large_table2.id
核心点就是使用distributed join,也就是hash join。Presto的这种配置类型会将左表和右表同时以join key的hash value为分区字段进行分区。所以即使右表也是大表,也会被拆分,相比broadcast join,这种join方式的会增加很多网络数据传输,效率慢。SELECT ...
FROM
t1
JOIN t2
ON t1.a1 = t2.a1 OR
t1.a2 = t2.a2
改为
SELECT ...
FROM
t1
JOIN t2
ON t1.a1 = t2.a1
union
SELECT ...
FROM
t1
JOIN t2
ON t1.a2 = t2.a2
使用Presto分析统计数据时,可考虑把多次查询合并为一次查询,用Presto提供的子查询完成。WITH tmp AS (
SELECT DISTINCT a1, a2
FROM t2
)
SELECT ...
FROM t1
JOIN tmp
ON t1.a1 = tmp.a1
union
SELECT ...
FROM t1
JOIN tmp
ON t1.a2 = tmp.a2;
和distinct类似, UNION有去重的功能, 所以会使用到内存,如果只是拼接两个或者多个SQL查询的结果, 考虑用UNION ALL来源 https://mp.weixin.qq.com/s/rtDm_L5qXk04lQiI2ayWkQ