• Presto的基本概念


    Presto是一款Facebook开源的MPP架构的OLAP查询引擎,可针对不同数据源执行大容量数据集的一款分布式SQL执行引擎。因为工作中接触到Presto,研究它对理解SQL Parser、常见算子的实现(如SQL中table scan,join,aggregation)、资源管理与调度、查询优化(如向量化执行、动态代码生成)、大数据下各个组件为何适用不同场景等等都有帮助。我希望通过这个系列可以了解一条SQL在大数据场景下该如何高效执行。233酱准备不定时持续更新这个系列,本文主要从Presto的使用举例,Presto的应用场景、Presto的基本概念三个部分来初步介绍Presto。

    presto 优点:

    • 完全基于内存的并行计算,Massively parallel processing(mpp)(大规模并行处理)模型
    • 流水线
    • 本地化计算
    • 动态编译执行计划
    • 小心使用内存和数据结构
    • 类BlinkDB的近似查询
    • GC控制
    • presto数据处理能力到达PB级别,支持查询数据源有hive、kafka、cassandra、redis、mongodb、sql server等

    presto 缺点:

    • No fault tolerance;当一个Query分发到多个Worker去执行时,当有一个Worker因为各种原因查询失败,那么Master会感知到,整个Query也就查询失败了,而Presto并没有重试机制,所以需要用户方实现重试机制。

    • Memory Limitations for aggregations, huge joins;比如多表join需要很大的内存,由于Presto是纯内存计算,所以当内存不够时,Presto并不会将结果dump到磁盘上,所以查询也就失败了,但最新版本的Presto已支持写磁盘操作,这个待后续测试和调研。

    • MPP(Massively Parallel Processing )架构;这个并不能说其是一个缺点,因为MPP架构就是解决大量数据分析而产生的,但是其缺点也很明显,假如我们访问的是Hive数据源,如果其中一台Worke由于load问题,数据处理很慢,那么整个查询都会受到影响,因为上游需要等待上游结果。

      presto不太支持存储过程,支持部分标准sql

      presto的查询速度比hive快5-10倍

      上面讲述了presto是什么,查询速度,现在来看看presto适合干什么

      适合:PB级海量数据复杂分析,交互式SQL查询,⽀持跨数据源查询

      不适合:多个大表的join操作,因为presto是基于内存的,多张大表在内存里可能放不下

      和hive的对比:

        hive是一个数据仓库,是一个交互式比较弱一点的查询引擎,交互式没有presto那么强,而且只能访问hdfs的数据

                presto是常驻任务,接受请求立即执行,全内存并行计算;hive需要用yarn做资源调度,接受查询需要先申请资源,启动进程,并且中间结果会经过磁盘。

        presto是一个交互式查询引擎,可以在很短的时间内返回查询结果,秒级,分钟级,能访问很多数据源

        hive在查询100Gb级别的数据时,消耗时间已经是分钟级了

        但是presto是取代不了hive的,因为p全部的数据都是在内存中,限制了在内存中的数据集大小,比如多个大表的join,这些大表是不能完全放进内存的,实际应用中,对于在presto的查询是有一定规定条件的,比比如说一个查询在presto查询超过30分钟,那就kill掉吧,说明不适合在presto上使用,主要原因是,查询过大的话,会占用整个集群的资源,这会导致你后续的查询是没有资源进行查询的,这跟presto的设计理念是冲突的,就像是你进行一个查询,但是要等个5分钟才有资源继续查询,这是很不合理的,交互式就变得弱了很多

    Presto架构:

                                   

    Presto查询引擎是一个Master-Slave的架构,由一个Coordinator节点,一个Discovery Server节点,多个Worker节点组成,Discovery Server通常内嵌于Coordinator节点中。

    • Coordinator负责解析SQL语句,生成执行计划,分发执行任务给Worker节点执行。

    • Worker节点负责实际执行查询任务。

    • Discovery Server:Worker节点启动后向Discovery Server服务注册,Coordinator从Discovery Server获得可以正常工作的Worker节点。

    • 如果配置了Hive Connector,需要配置一个Hive MetaStore服务为Presto提供Hive元信息,Worker节点与HDFS交互读取数据。

    一个查询分解为多个stage, 每个stage拆分多个task,每个task处理一个or多个split ,一个task被分解为一个或多个Driver。

    1、基本概念

    • Connector是适配器,用于Presto和数据源(如Hive、RDBMS)的连接。你可以认为类似JDBC那样,但却是Presto的SPI的实现,使用标准的API来与不同的数据源交互。每个catalog都有一个特定的Connector。如果你使用catelog配置文件,你会发现每个文件都必须包含connector.name属性,用于指定catelog管理器(创建特定的Connector使用)。一个或多个catelog用同样的connector是访问同样的数据库。例如,你有两个Hive集群。你可以在一个Presto集群上配置两个catelog,两个catelog都是用Hive Connector,从而达到可以查询两个Hive集群。

    Presto 使用 Catalog、Schema和Table 这3层结构来管理数据

    • catalog:就是数据源。每个数据源连接都有一个名字,一个Catalog可以包含多个Schema,大家可以通过show catalogs 命令看到Presto已连接的所有数据源。

    • schema:相当于一个数据库实例,一个Schema包含多张数据表。通过以下方式可列出catalog_name下的所有 Schema:show schemas from 'catalog_name'

    • Table:数据表,与RDBMS上的数据库表意义相同。通过以下方式可查看'catalog_name.schema_name'下的所有表:show tables from 'catalog_name.schema_name'

    在Presto中定位一张表,一般是catalog为根,例如:一张表的全称为 hive.test_data.test,标识hive(catalog)下的 test_data(schema)库中 test 表。可以简理解为:数据源的类别.数据库.数据表。

    • 语句(Statement):Presto执行ANSI兼容的SQL语句。当Presto提起语句时,指的就是ANSI标准的SQL语句,包含着列名、表达式和谓词。之所以要把语句和查询分开说,是因为Presto里,语句知识简单的文本SQL语句。而当语句执行时,Presto则会创建查询和分布式查询计划并在Worker上运行。

    • 查询(Query):当Presto解析一个语句时,它将其转换为一个查询,并创建一个分布式查询计划(多个互信连接的stage,运行在Worker上)。如果想获取Presto的查询情况,则获取每个组件(正在执行这语句的结点)的快照。查询和语句的区别是,语句是存SQL文本,而查询是配置和实例化的组件。一个查询包含:stage、task、split、connector、其他组件和数据源。

    • Stage:当Presto执行查询时,会将执行拆分为有层次结构的stage。例如,从hive中的10亿行数据中聚合数据,此时会创建一个用于聚合的根stage,用于聚合其他stage的数据。层次结构的stage类似一棵树。每个查询都由一个根stage,用于聚合其他stage的数据。stage是Coordinator的分布式查询计划(distributed query plan)的模型,stage不是在worker上运行。

    • Task:由于stage不是在worker上运行。stage又会被分为多个task,在不同的work上执行。Task是Presto结构里是“work horse”。一个分布式查询计划会被拆分为多个stage,并再转为task,然后task就运行或处理split。Task有输入和输出,一个stage可以分为多个并行执行的task,一个task可以分为多个并行执行的driver。

    • Split:Task运行在split上。split是一个大数据集合中的一块。分布式查询计划最底层的stage是通过split从connector上获取数据,分布式查询计划中间层或顶层则是从它们下层的stage获取数据。

    Presto调度查询,coordinator跟踪每个机器运行什么任务,那些split正在被处理。

    • Driver:Task包含一个或多个并行的driver。Driver在数据上处理,并生成输出,然后由Task聚合,最后传送给stage的其他task。一个driver是Operator的序列。driver是Presto最最低层的并行机制。一个driver有一个输出和一个输入。

    • Operator:Operator消费,传送和生产数据。如一个Operator从connector中扫表获取数据,然后生产数据给其他Operator消费。一个过滤Operator消费数据,并应用谓词,最后生产出子集数据。

    • Exchange:Exchange在Presto结点的不同stage之间传送数据。Task生产和消费数据是通过Exchange客户端。

    Presto的使用举例

    比如说,你想对存储在不同数据源中的数据,如HDFS、Mysql、HBase等通过一个SQL做查询分析,那么只需要把每一个数据源当成是Presto的Connector,对应实现Presto SPI暴露出的Connector API就可以了。

    图片hbase 和 es 的Join查询举例

    Presto官方版和Presto社区版已经支持了很多Connector,社区版略胜一筹。至于两者有何区别,吃瓜群众可以前往文末参考资料[4]。简而言之,都主要由Facebook那帮大佬核心维护。社区版更新更为频繁,但高版本需要JDK11才能支持;官方版JDK8就行,官方版的Star数是社区版的10倍左右,选哪个就一目了然了吧。

    Presto的应用场景

    Presto是为了处理TB/PB级别的数据查询和分析,它是OLAP(Online Analytical Processing)领域的一个计算引擎。参考资料[1]提到了Presto在Facebook中的使用场景有:

    报表和大盘查询

    做过报表和大盘的小伙伴应该对这个场景下复杂的SQL有所了解。这个场景下的使用用户是Facebook内部或外部人员,通常要求:高QPS,低时延(<1s)

    Adhoc分析

    Ad hoc是拉丁文「for this purpose」的意思,Adhoc query的查询特点是海量、实时、灵活。数据量如PB级别以上,时延秒-分钟级别,灵活性举例子如下:

    var adhoclQuery = "SELECT * FROM table WHERE id = " + myId;

    var sqlQuery = "SELECT * FROM table WHERE id = 1";

    adhoclQuery的结果取决于参数“myId”的值,它的结果不能被预计算。sqlQuery的结果每次执行可认为都一样,它的结果可以被预计算。

    典型应用场景如:用户趋势分析,产品市场洞察等。主要用户是内部数据分析人员。

    批处理

    批处理通常是指更大数据量的一个分析,可容忍高时延(小时-天级别)。Presto是为了低时延而设计的,它属于内存型的MPP架构。并不适合类似Spark那样的长时间离线跑批。参考资料[1]的视频中分析了两者架构的区别,Presto跑批的限制。这里我截几张PPT帮助大家理解:
    两者的架构区别:

    图片
    Presto跑批的限制原因:
    图片
    Presto跑批的条件:
    图片

    所以他们提供了Presto on Spark方案,这样做的好处是可以统一用户使用的SQL方言差异,UDF差异。

    图片

    当然,业界除了Facebook还有公司把Presto跑在Spark上来跑批吗?我没有搜到相关信息。

    Presto的基本概念

    前面主要谈了Presto的使用场景,下面简要从 Presto的架构和基本术语上介绍Presto。

    Presto架构

    Presto的架构图如下:

    图片
    Presto集群包含1个Coordinator节点和1-多个Worker节点。

    Coordinator节点 负责接受客户端请求、解析SQL语句、生成并优化分布式逻辑执行计划、将计划中的任务调度到Worker节点上,并跟踪Worker节点和任务的执行状态。

    Worker节点 负责任务的执行,接受Coordinator节点的调度。

    从中我们可以粗略看出一条SQL在Presto中的执行过程为:

    1).Client发送一个SQL语句到Coordinator节点
    2).Coordinator节点把请求放到队列中,解析和分析其中的SQL语句;生成并且优化分布式逻辑执行计划。
    3).Coordinator节点会把这个Plan分解为任务,由多个Worker分布式执行。

    要想了解具体的SQL执行过程,我们得先介绍下Presto的基本概念,也为下篇介绍「Presto为什么是OLAP领域的实时计算引擎」的文章作准备>_<

    基本术语

    我们很容易知道 statements 和 queries 的意思。作为一个使用者我们也应该熟悉 stages、 splits 这些概念使Presto尽可能高效执行queries;作为一个Presto管理员,应该理解 stages 是如何映射为tasks的,包含 drivers 集合 的 task 是如何处理数据的。以下将从一般到具体介绍Presto的基本术语。

    Server Types

    Presto包含两种类型的服务端节点:coordinators 和 workers。

    Coordinator

    Presto中的Coordinator节点负责解析SQL语句,生成并优化物理执行计划,管理Presto worker节点。它是Presto运行的“大脑”。它也是客户端提交SQL语句的节点。每个运行的Presto集群包含1个Coordinator节点和1-多个Worker节点。一个服务示例可同时担任这两种节点角色。

    Coordinator节点一直跟踪每个Worker节点的状态和协调查询计划的执行。Coordinator生成一个物理执行计划模型,它包含一系列的stages,而stages会转化为一系列的任务跑在workers节点上。

    Coordinator通过REST API和workers 、 clients通信。

    Worker

    Worker节点负责执行tasks,处理数据。它从connectors中捞取数据,并且Worker节点之间可交换中间数据。coordinator节点负责合并workers的结果,并且返回结果给Client。

    当一个Worker节点开始工作后,它会把自己注册到coordinator的注册服务上,从而使Coordinator节点可将task调度到自己执行。

    Workers和其他Workers、coordinators之间都是通过REST API通信。

    Data Sources

    诸如connector, catalog, schema, and table这些术语,都是和Presto的模型中:一种特定的数据源有关。

    Connector

    connector是Presto中的一个数据源,可以是Hive、Mysql、Elasticsearch、HBase等。你可以把connector认为是一种数据库驱动,只要实现Presto  SPI 中暴露的相关接口,就可以接入一种Connector。

    Presto自带一些connectors:如JMX,System connector用来获取system tables的,Hive connector,TPCH connector 用来性能测试用的,等等。

    每一个catalog和一个特定的connector关联。每一个catalog配置文件中有一个connector.name属性,它是被catalog manager用来为一个给定的catalog创建一个connector。一个catalog可以使用相同的connector获取类似数据库的两个实例。

    Catalog

    Presto catalog包含schemas和通过Connector持有的数据源引用。比如:你可以配置一个ES catalog,就可以通过ES Connector提供从ES中获取数据。

    #elasticsearch.properties

    connector.name=elasticsearch
    elasticsearch.host=es host
    elasticsearch.port=9200
    elasticsearch.default-schema-name=es

    当你在Presto上执行SQL时,你就在运行1-多个catalogs.在Presto上定位一张表,是通过一个catalog的全限定名确定的,如hive.test_data.test代表在hivecatalog,test_data schema 下的一张test table.

    Catalogs属性文件是存储在Presto配置目录的,默认是Presto主安装文件下的etc目录下。

    Schema

    Schemas是一种组织tables的方式。一个catalog和一个catalog定义了一个可被查询的table集合。对于MySQL这种关系型数据库,Presto的schema是和MySQL中的schema相同的概念。对于其他类型的connector,如ES, Presto的schema是用来组织一些表到特定的schema中,从而使底层的数据源能够在Presto层面说得通。

    Table

    table是一组无序的Row集合,Row是一组有类型的column集合。和关系型数据库中的概念一样,table的映射是由connector中定义的。

    Query Execution Model

    Presto执行SQL语句,并且转化为执行计划,在由coordinator 和 workers组成的分布式集群上运行。

    Statement

    Presto执行兼容ANSI标准的SQL。这些SQL statements包含子句,表达式,条件。
    Presto把Statement 和 Query区分开是因为:在Presto中,statements是指Client提交上来的SQL语句,如:

    SELECT * FROM table WHERE id = 1

    query是指Presto执行statement时,生成的一个物理执行计划,并且之后分布式的在一系列workers上执行它。

    Query

    当Presto解析一个statement时,它会把statement转化为一个query,并且创建一个分布式的执行计划,然后转化为一系列的有关联性的stages运行在Presto workers上。当你在Presto获取一个query的信息时,得到的是每个参与执行的组件的一个当前结果快照。

    statement可认为是Client提交上来的SQL语句,query指的是执行一个statement有关的配置和组件实例信息。query围绕着stages, tasks, splits, connectors,其他组件和数据源一起工作,以产生最终结果。

    Stage

    当Presto执行一个query时,它会把执行分为一个有层次结构关系的stages.比如SQL语句:

    图片
    会先转化为逻辑执行计划:
    图片
    然后会转化为实现这个分布式逻辑执行计划的一个层次结构的stage:
    图片

    这个层次结构的stages可以理解为一个一个树。每个query都有一个root stage负责其他stages的输出结果聚合。stages是coordinator节点用来生成一个分布式查询计划的模型,但是stages它们自己并不跑在Presto workers节点上。

    Task

    一个stage是由一系列的tasks分布式运行在Presto workers上。

    在Presto架构中,task是“work horse”。因为分布式查询计划被分解为一系列stage,然后被转换为task,这些task随后执行或被进一步split。一个task有输入和输出,就像一个stage可以有一系列的tasks并行执行一样,一个task可以由一系列的drivers并行执行。

    Split

    Split是较大数据集的一个分片。分布式查询计划的最低级别的stage(如上图中的Stage3/Stage4)通过来自connectors得到的splits集合获取输入数据,更高级别的中间Stage(如上图中的Stage2/Stage1)从下一层stage中获取输入数据。

    当Presto调度一个query时,coordinator节点会查询连接器的SPI接口获得一个表可用的所有split集合。coordinator跟踪哪些机器正在运行哪些task,以及哪些任务正在处理哪些split。

    Driver

    Task包含一个或多个并行的driver。driver对数据进行操作,并结合operators产生输出,然后结果由一个task聚合,然后传递到另一个stage的另一个task。driver是一系列operators实例,或者您可以将driver看作内存中的operator的物理集合。它是Presto体系结构中并行的最低级别。一个driver有一个输入和一个输出。

    Operator

    一个operator消费、转换和生产数据。例如,一个table scan operator从一个connector中获取数据并生产出可由其他operator消费的数据,一个filter operator通过对输入数据应用谓词(过滤条件)并生成一个子集。

    Exchange

    Exchanges为一个query的不同stage在Presto节点之间传递数据。task使用一个exchange client,生产数据到一个output buffer中,并且消费其他task产生的数据。

  • 相关阅读:
    Mac下pyhon+selenium滚动截长图出现中间一部分页面截取不到问题的原因以及解决方案
    flask 访问上传图片网页出现报错: jinja2.exceptions.TemplateNotFound: /Users/xxx/Documents/python/pack/index.html解决方案
    Mac启动的时候自动执行python脚本
    selenium自动化测试使用xpath定位如下报错(The result of the xpath expression "//span[@class='numrows']/font/text()" is: [object Text]. It should be an element.)解决方案
    python+selenium无头模式访问网站被禁止访问导致元素无法定位获取的问题定位过程以及解决方案
    python+selenium+PIL+glob+numpy实现网页截长图
    安装python中某些模块出现如下错误提示ERROR: Could not find a version that satisfies the requirement glob3 (from versions: none)解决方案
    Mac下设置定时执行python脚本任务踩坑日记
    python的进程池,线程池的使用
    需改commit信息
  • 原文地址:https://www.cnblogs.com/pengpenghuhu/p/14279868.html
Copyright © 2020-2023  润新知