Presto
概述
Presto是一个开源的分布式SQL查询引擎,数据量支持GB到PB字节,主要用来处理海量数据的秒级查询场景,虽然Presto可以解析SQL,但它不是一个标准的数据库。不是MySQL、Oracle的代替品,也不能用来处理在线事务(OLTP)
基础概念
- Connector
与关系型数据库的connector相似,每个connector实现了Presto的SPI,这允许上层开发人员使用标准的PrestoAPI操作不同数据源。 - Catalog
一个Catalog包含Schemas个Connector,Catalog需要在配置文件中进行配置。 - Schema
Schema是一种表的组织方式,Catalog+Schema确定了一系列可查询的表,因此在Query时,是catalog.schemanema.tablename
执行流程
当一个语句输入到查询出结果分成两个步骤:
- 生成逻辑执行计划
-
生成物理执行计划
整体流程如下:
执行流程.jpg
简单描述:
当用户通过CLI提交的Statement经过之后Sqlparse进行分析之后形成AST语句,经过简单的分析(Analysis)之后形成未优化的plan计划,再对上述未进行优化的逻辑执行计划进行优化(Optimizer)进而形成逻辑执行计划。上述的文字基本就是逻辑执行计划的生成过程了;
之后对逻辑中生成的plan进行拆分,拆分成多个subplan,而每一个subplan就可以直接提交到一个或多个worker进行执行,进入worker的subplan就是图中的LocalExecutionPlan了。而这一步的将逻辑执行计划的plan进行拆分以较高的并行度去执行的过程就是物理执行计划。
Subplan
物理执行计划中的subplan又几个重要的属性,一定需要了解的,分别是:planDistribution、outputPartitioning、partitionBy
-
PlanDistribution
PlanDistribution表示一个查询Stage的分发方式,逻辑执行计划图中的4个SubPlan共有3种不同的PlanDistribution方式:Source表示这个SubPlan是数据源,Source类型的任务会按照数据源大小确定分配多少个节点进行执行;Fixed表示这个SubPlan会分配固定的节点数进行执行(Config配置中的query.initial-hash-partitions参数配置,默认是8);None表示这个SubPlan只分配到一个节点进行执行。在下面的执行计划中,SubPlan1和SubPlan0 PlanDistribution=Source,这两个SubPlan都是提供数据源的节点,SubPlan1所有节点的读取数据都会发向SubPlan0的每一个节点;SubPlan2分配8个节点执行最终的聚合操作;SubPlan3只负责输出最后计算完成的数据。
执行流程2.png
- OutputPartitioning
OutputPartitioning属性只有两个值HASH和NONE,表示这个SubPlan的输出是否按照partitionBy的key值对数据进行Shuffle。
Hash主要针对下游节点有多台机器,则会按照hash或round robin值选择一个下游机器进行输出
None主要针对下游节点只有一台机器,该subplan固定的发往到这个这个下游的机器
在上面的执行计划中只有SubPlan0的OutputPartitioning=HASH,所以SubPlan2接收到的数据是按照rank字段Partition后的数据。 - partitionBy
架构
Presto架构1.png
优点:
- Presto基于内存运算,减少了磁盘IO,计算快
- 能够连接多个数据源,支持的数据源丰富
- 支持跨数据源连表查询,这得益于架构中对不同种类的数据源都划分成Schema+Table的统一格式,为跨库查询提供基础
缺点:
Presto能够处理PB级别的海量数据分析,但Presto并不是吧PB数据一次放入内存中计算,而是边读边计算,再清理内存的模式,这种读一部分数据计算之后的结果会先在内存中保存为临时数据。这就可能再查询中有大量的临时数据,导致速度下降。
使用层
- Shell方式使用Presto
- 使用Java API方式使用
- 使用yanggishama、Hue等可视化界面操作Presto
元数据管理
默认自己管理
查询优化
Join操作
多表Join时,按照表的数据量多少以递增的顺序进行Join,Presto查询时,会将前面的表放入内存中,具体流程可以查看官网
Exist操作
在数据量比较大时,使用inner join取代exists与 使用left join取代 not exists性能上可以得到较大的提升
集群调优
- task.concurrency
说明:单个Task任务并发度,在Join与Agg(聚合)操作有帮助,该值不是越大越好,需要根据场景,总结来说,对于经常需要查询的集群来说,较低的值比较好,这避免了CPU的线程上下文切换带来的影响;对于查询任务较少的集群,该值可以适当增加,以提高并行速度。
查看官网 - spill-enabled
建议开启,该配置默认是不开启的,在aggregations, joins (inner and outer), sorting, and window functions操作中,如限制的内存大小快要到达时,可以将内存中计算出的一些中间结果溢出到磁盘,最后从磁盘中逐步读取数据返回。
查看官网
还有很多,在之后的生产环境中使用的时候会持续更新
部署
- 拉取docker,地址为:docker pull trinodb/trino
// 启动容器
docker run -p 8080:8080 --name trino trinodb/trino
// 进入容器
docker exec -it trino bash
// 这里以添加kudu catalog 为例
cd /usr/lib/trino
// 创建名称为kudu_vm的catalog
vi kudu_vm.properties
// 编写kudu catalog相关信息
这里就忽略了,具体配置也很简单,可以直接查看官网kudu connectors中的实例程序,包括之后的使用案例
多源表Join
-
创建kudu一张表ods_users,表结构如下:
使用1.jpg
-
同理在mysql中创建一张tt,表结构如下:
使用2.jpg
-
分别向两张表中插入数据
使用3.jpg
使用4.png
-
Join关联
使用5.jpg
这就是将不同数据源进行join。











网友评论