是一个开源的分布式Sql查询引擎,数据量支持到GB到PB级别,主要用处理秒级查询的场景
注意:虽然Presto可以解析SQL,但它不是一个标准的数据库,不是mysql,Oracle的替代品,也不能用来处理自爱西安事务(OLTP)
Presto的架构
由一个Croodinator和多个Worker组成
•Presto Coordinator
–是主架构
–用来接受客户端的请求(解析sql)
–发送给Presto Worker
–可以对接多种多样的sql(hive,kafka,redis,关系型数据库)
–去hive访问元数据,再去hdfs获取源数据
•Catalog就是一个数据源
–Hive Connector
•连接器,不同的数据源,不同的连接器
–Schema
•hive的数据库的概念差不多
–Table
•和hive的table一致
流程:
•由客户端提交查询,从Presto命令行CLI提交到Coordinator
•coordinator解析查询计划,然后把任务分发给worker执行
•worker负责执行任务,和处理数据
•Catolog表示数据源,一个Catelog含Schema和Connector
•Connector是适配器,用于Presto和数据源(Hive,Redis等)的连接,类似于JDBC
•Schema类似于Mysql中数据库,Table类似于Mysql中表
•Coordiator是负责从Worker获取结果并返回最终结果给Client
Presto和MapReduce对比
•比MR快5到10倍
•内存足够大,中间计算结果不落磁盘,若内存不够大,中间结构还是落地磁盘的
impala领先于presto,但是presto再数据源支持上更丰富
Presto的优缺点
优点
•Presto基于内存运算,减少硬盘IO,计算更快
•连接多个数据源,跨数据源表查
缺点
•presto不是把PB级数据都放在内存中计算,根据场景,若AVG,Count,是边读数据边计算,再清理内存,再计算,这种耗的内存不高
•连表查,可能产生大量的临时表,速度变慢,反而不如Hive
Presto优化之数据存储
•合理设置分区
–Presto会根据元数据信息读取分区数据,合理的分区能减少Presto数据取量,提升查询性能
•列式存储
–Presto对ORC文件读取做了特定优化,建议使用ORC格式存储
•压缩
–数据压缩减少节点间数据传输对IO带宽压力,对即席查询需要快速解压
–建议Snappy压缩
Presto优化之查询Sql
•只选择使用的字段
–采用列式存储
–建议选择需要的字段加快字段的读取,减少数据量
–避免*读取
•过滤条件必须加上分区字段
–对于由分区的表,where语句中优先使用分区字段进行过滤
–acct_day是分区字段
–visit_time是具体访问时间
–[GOOD]: SELECT time, user, host FROM tbl where acct_day=20171101
[BAD]: SELECT * FROM tbl where visit_time=20171101
•group by语句优化
–合理安排group by语句中字段对性能有一定提升
–将group by语句中字段按照每个字段去重数据多少进行降序
•order by使用Limit
–Oreder by需要扫描数据到单个worker节点进行排序
–导致单个worker需要大量内存
–若在取TOPN,使用limit可以减少排序计算和内存压力
–[GOOD]: SELECT * FROM tbl ORDER BY time LIMIT 100
[BAD]: SELECT * FROM tbl ORDER BY time
•使用Join语句时将大表放在左边
–Presto中Join的默认算法时broadcast join
•即将join左边的表分割多个worker,然后将Join右边的表数据整个复制一份发送到每个worker进行计算
•若右边表数据量太大,会报内存溢出错误
•[GOOD] SELECT ... FROM large_table l join small_table s on l.id = s.id
[BAD] SELECT ... FROM small_table s join large_table l on l.id = s.id
注意事项
•字段名引用
–避免关键字冲突
–mysql对字段加反引号·
–Presto对字段加双引号分割
–若字段名称不是关键字,可以不加这个双引号
•时间函数
–对Timestamp,需要比较的时候,需要添加Timestamp关键字,而mysql中对Timestamp可以直接进行比较
–/*MySQL的写法*/
SELECT t FROM a WHERE t > '2017-01-01 00:00:00';
/*Presto中的写法*/
SELECT t FROM a WHERE t > timestamp '2017-01-01 00:00:00';
•不支持insert overwrite语法
–Presto 中不支持 insert over write 语法,只能先delete然后insert into
•parquet格式
–目前不支持parquert格式,支持查询,但不支持insert
注意:presto不识别&这个符号,我搞了我好久啊