Presto基础知识
Presto缓存
引入Presto缓存之前 BackgroundHiveSplitLoader 使用底层的文件系统直接进行数据的读写;
引入Presto缓存机制之后,底层的文件系统被被CachingFileSystem 代理一层
CachingFileSystem 有两个子类,根据你选用的底层缓存引擎的不同可能会是下面的两个之一:
AlluxioCachingFileSystem /əˈluːʒ(ə)n/: 在Presto Worker本地利用磁盘进行了数据的缓存
FileMergeCachingFileSystem: 在本地缓存检查这个数据块是否已经读取过了,通过底层的文件系统来从远端来读取数据,读取到数据之后再添加到本地的磁盘缓存
Presto自己实现FileSystem接口,添加cacheable参数,确定是否缓存数据
如何保证缓存的命中率?
即,相同数据请求打到同一节点上,本地读取缓存进行查询提速
节点分发策略:NodeSelectionStrategy:1.指定节点。 2.尽量指定节点 3.随机指定节点
将worker节点进行hash计算,优先选择Prefered Nodes,判断是否繁忙TotalSplitCount,若繁忙则再选择最空闲的节点。
Presto数据类型
Type接口封装,定义了类型定长、变长属性。
定长:
Boolean: 用 Byte
来表示, 0-1 表示 是否
float:内部对应real ,底层用int表示,因为block类针对的都是int
其余:Decimal、时间类型、字符串、IpAddress、Geo等
变长:
varchar(n)
Presto Slice
Slice是Presto里面用来对内存高效地、自由地进行操作的接口。是对sun.misc.Unsafe的包装,更加安全易用。
Slice的结构
Slice里面是通过三个参数来确定一个内存地址: base , address , size
base:是通过JVM分配出来的内存,在JVM层面是int数组、byte数组的对象,而对Slice来说这就是我们要操作的内存块。
address:Unsafe常量,表示byte数组里面第一个元素的地址离整个byte数组地址头的偏移量(为什么会有这么一个偏移量?因为数组由元数据和数据组成,默认从16个字节以后开始存储数据)
size:是我们这块内存的大小,一般来说就是 base 底层所对应的内存的大小(in bytes), 或者更小一点
TupleDomain
TupleDomain 是用来表达 table 里面各个字段的约束条件、取值范围的。内部维护了一个字段名到对应的Domain的映射关系,表示一个表里面多个字段的取值约束条件。
Group by 分组聚合操作的逻辑计划执行流程
stage-0 output
stage-1 exchange aggregation project 读取上游outputbuffer数据,聚合
stage-2 tablescan filter project aggregation 扫描数据,过滤,局部聚合
生成Stage
生成逻辑执行计划过程中,递归原root树生成
生成Task
多个Stage,谁首先生成Task?
由ExecutionPolicy决定,默认:AllAtOnceExecutionPolicy
生成几个Task?
Stage两种类型,数据源读数据和非数据源读数据
数据源读数据,根据具体的数据源类型来确定
如果从connector中拿到的spilt是必须本地访问的,task数取决于数据分布的节点数。
如果从connector中拿到的spilt是远程访问的,取决于limit和presto node个数的较小值。
非数据源读数据
单节点或hash_partition_count决定
Task状态
内部接口每100毫秒调用一次TaskInfoFetcher
Count(distinct) 优化
select A, count(distinct B) from T group by A.
转换成
select A, count(B) from (select A, B from T group by A, B) group by A.