前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Presto介绍及常用查询优化方法总结

Presto介绍及常用查询优化方法总结

原创
作者头像
硬核林川
修改2021-05-10 10:43:05
2.5K0
修改2021-05-10 10:43:05
举报
文章被收录于专栏:硬核林川

​1、Presto简介

Presto是Facebook开源的MPP(Massive Parallel Processing)SQL引擎,其理念来源于一个叫Volcano的并行数据库,该数据库提出了一个并行执行SQL的模型,它被设计为用来专门进行高速、实时的数据分析。

Presto是一个SQL计算引擎,分离计算层和存储层,其不存储数据,通过Connector SPI实现对各种数据源(Storage)的访问。

1.1 架构

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交互,读取原始数据。

1.2 实现低延时的原理

Presto是一个交互式查询引擎,我们最关心的是Presto实现低延时查询的原理,以下几点是其性能脱颖而出的主要原因:

  • 完全基于内存的并行计算
  • 流水线
  • 本地化计算
  • 动态编译执行计划
  • 小心使用内存和数据结构
  • GC控制
  • 无容错

2、Presto查询优化

2.1 存储优化

① 合理设置分区

与Hive类似,Presto会根据元信息读取分区数据,合理的分区能减少Presto数据读取量,提升查询性能。

② 使用列式存储

Presto对ORC文件读取做了特定优化,因此在Hive中创建Presto使用的表时,建议采用ORC格式存储。相对于Parquet,Presto对ORC支持更好。

③ 使用压缩

数据压缩可以减少节点间数据传输对IO带宽压力,对于即席查询需要快速解压,建议采用snappy压缩

④ 预先排序

有条件的话提前做好排序,对于已经排序的数据,在查询的数据过滤阶段,ORC格式支持跳过读取不必要的数据。

比如对于经常需要过滤的字段可以预先排序。

2.2 查询优化

① select时只选择必要字段,避免使用 * 号

② 过滤条件加上分区字段,减少查询数据量

③ 合理安排Group by语句中字段顺序对性能有一定提升

将Group By语句中字段按照每个字段distinct数据多少进行降序排列。示例中uid是用户id,比性别数据大很多。

代码语言:javascript
复制
[GOOD]: SELECT GROUP BY uid, gender 
[BAD]:  SELECT GROUP BY gender, uid

④ Order by时使用Limit

Order by需要扫描数据到单个worker节点进行排序,导致单个worker需要大量内存。如果是查询Top N或者Bottom N,使用limit可减少排序计算和内存压力。

⑤ 用regexp_like代替多个like语句

Presto查询优化器没有对多个like语句进行优化,使用regexp_like对性能有较大提升

代码语言:javascript
复制
[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函数性能更好

2.3 Join优化

① 使用Join语句时将大表放在左边

Presto中join的默认算法是broadcast join,即将join左边的表分割到多个worker,然后将join右边的表数据整个复制一份发送到每个worker进行计算。

如果右边的表数据量太大,则可能会报内存溢出错误。

② 如果左表和右表都比较大

为防止内存溢出,做如下配置:

1)修改配置distributed-joins-enabled (presto version >=0.196)

2)在每次查询开始使用distributed_join的session选项

代码语言:javascript
复制
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方式的会增加很多网络数据传输,效率慢。

③ 多个join的OR条件使用union代替

代码语言:javascript
复制
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

④ 使用WITH语句

使用Presto分析统计数据时,可考虑把多次查询合并为一次查询,用Presto提供的子查询完成。

代码语言:javascript
复制
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;

⑤ 尽量用UNION ALL代替UNION

和distinct类似, UNION有去重的功能, 所以会使用到内存,如果只是拼接两个或者多个SQL查询的结果, 考虑用UNION ALL


​资深数据专家,关注大数据、数仓、Java、Flink/Spark/Hadoop、OLAP等技术,微信搜索【硬核林川】公众号,回复【资料】可领取最新的大数据视频教程和书籍。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ​1、Presto简介
    • 1.1 架构
      • 1.2 实现低延时的原理
      • 2、Presto查询优化
        • 2.1 存储优化
          • 2.2 查询优化
            • 2.3 Join优化
            相关产品与服务
            云数据库 MySQL
            腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档