引言
查询分析是大数据要解决的核心问题之一,而SQL作为查询分析中使用最简单、最广泛的的语言之一,必然而然的催生了许多支持在Hadoop上使用SQL的系统,这就是所谓的SQL-on-Hadoop系统,其中大众熟知的Hive就是最早的SQL-on-Hadoop系统。
经过若干年的发展,SQL-on-Hadoop系统已经百花齐放,按照架构划分这些系统大致可以分为以下几类:
- MapReduce架构系统:如Hive,这类系统是在MapReduce计算框架上封装了一个SQL语义层,在运行过程中把SQL转换为MapReduce程序来执行
- MPP架构系统:如Impala、Presto、Drill等,这类系统采用MPP(Massively Parallel Processing)架构,而非MapReduce
- 预计算系统:如Druid、Kylin等,这类系统主要特点是对数据进行预计算,并将结果保存,而在查询时直接获取相应结果值
本文主要是对这些系统做了一个基本总结,并简单介绍了一些主流系统的架构以及处理流程。下表是按照时间顺序,对这些系统的一个概述,包括技术特点和主导公司等。
项目名称 | 时间点 | 技术特点 | 主导公司 |
---|---|---|---|
Apache Hive | 2008年进入Apache,2010年毕业 | 一款基于HDFS的MapReduce计算框架,提供类SQL的数据查询功能,本质是将SQL转换为MapReduce任务运行 | 初期由Facebook开发,后被各大公司广泛接受 |
Apache Spark | 2010年进入Apache,2014年毕业 | 数据在内存中以RDD(Resilient Distributed Datasets)表示,DataFrame是其核心编程抽象,同时也支持交互式查询和流计算 | Databricks |
Cloudera Impala | 2012年进入Apache,2017年11月毕业 | 一款使用C/C++实现的MPP SQL查询引擎,使用HDFS作为存储,并支持列存 | Cloudera |
Apache Drill | 2012年进入Apache,2014年毕业 | 以Google Dremel论文为基础,一个MPP数据查询引擎,支持schema free的交互式数据查询 | MapR |
Presto | 2013年开源 | 基于内存的计算引擎,本身并不存储数据,支持跨数据源的级联查询 | |
Stinger Initiative | 2013年 | 对Hive的性能优化和提升 | Hortonworks |
Apache Phoenix | 2013年进入Apache,2014年5月毕业 | 构建在HBase上的一个SQL层 | 初期由Salesforce开发 |
Apache Tajo | 2013年进入Apache,2014年5月毕业 | 基于Hadoop的数据仓库和SQL数据查询执行引擎 | 由Database Lab., Korea University开发 |
Apache Flink | 2014年4月进入Apache,2014年12月毕业 | 流式的数据流执行引擎,基于流计算来模拟批计算,分别提供了流处理和批处理API | Data Artisans |
Apache Kylin | 2014年11月进入Apache,2015年11月毕业 | 使用CUBE技术做多维数据预计算和聚合 | 初期由ebay开发,现由Kyligence主导 |
Apache HAWQ | 2015年进入Apache,2018年5月毕业 | Hadoop原始大规模并行SQL分析引擎,支持ACID事物特性 | Hortonworks |
Apache Trafodion | 2015年进入Apache,孵化中 | 构建在HBase上的一个SQL层 | HP实验室 |
Apache Hive
Apache Hive是Hadoop生态系统中最早的SQL引擎,它可以将结构化数据文件映射为一张数据库表,并提供类SQL查询功能。Hive本质上是在MapReduce计算框架上封装了一个SQL语义层,并在运行过程中把SQL转换为MapReduce程序来执行。
Hive通过用户交互接口接收SQL后,其Driver结合元数据将SQL翻译成MapReduce程序,并提交到Hadoop中执行,最后将执行结果输出,其架构如下图所示:
主要组成部分包括:
- user interface:即用户接口,包含CLI(命令行),JDBC/ODBC等
- Metastore:即元数据,包括表名、表的数据所在目录等;默认元数据存储在自带的derby数据库中,推荐使用MySQL
-
Driver:即驱动器,包含以下几个组件:
- 解析器(SQL Parser):将SQL转换成抽象语法树(AST),并对AST进行语法分析
- 编译器(Compiler):将AST编译生成逻辑执行计划
- 优化器(Query Optimizer):对逻辑执行计划进行优化
- 执行器(Execution):把逻辑执行计划转换成可以运行的物理计划
Hive提供的类SQL查询功能避免了开发人员书写复杂的MapReduce程序,极大的简化了MapReduce程序的开发,大大减少了相应的学习成本。随着技术的不断进步,Hive的执行引擎也不断发展,尤其是有了Tez之后,其性能有了很大的改进。不过,其不足依旧很明显,即处理速度慢,因而比较适合运行在批处理场景中,而不适合交互式查询等对时延要求高的场景中。
Apache Spark
Spark是一个通用的大数据计算框架,期望使用一个技术栈来解决大数据领域包括批处理、流计算、交互式查询、图计算和机器学习在内的各种计算任务,其软件栈如下图所示:
其中的Spark SQL组件是一个用于处理结构化数据的组件,它吸收了一个叫Shark(Hive-on-Spark)的项目。Spark SQL中最重要的一个概念就是DataFrame,它是带有Shema信息的RDD,类似于传统数据库中的二维表格。Spark SQL支持将多种外部数据源的数据转化为DataFrame,包括Json、Parquet等,并可以通过将其注册为临时表,然后使用SQL来处理和分析这些数据。Spark SQL的运行流程包含以下几步,如图所示:
包含以下几个步骤:
- SQL语句经过SqlParser解析成UnresolvedLogicalPlan
- Analyzer结合catalog进行绑定,生成LogicalPlan
- Optimizer对LogicalPlan优化,生成OptimizedLogicalPlan
- SparkPlan将OptimizedLogicalPlan转换成PhysicalPlan
- prepareForExecution()将PhysicalPlan转换成executedPhysicalPlan
- PhysicalPlan执行得到最终结果RDD
传统的MapReduce程序中Map和Reduce阶段的结果都要写磁盘,这大大降低了系统性能。Spark使用RDD作为基本数据结构,数据常驻内存,所以计算速度得到了很大提高。但是当内存不足时,其计算速度会大大降低,甚至容易出现OOM错误。
Apache Impala
Apache Impala是一款基于HDFS/HBase的MPP查询引擎,其架构如下图所示:
主要组成部分包括:
- Impalad: 即Impala Daemon(Impala守护进程);它运行在集群的每个node上,负责接收客户端的查询请求,对查询进行并行化处理。其中接收查询请求的Impalad为Coordinator,Coordinator对查询语句处理后生成执行计划,再把执行计划分发给具有相应数据的其它Impalad执行,其他Impalad执行完成后,把结果发送回
Coordinator,由Coordinator构建最终结果,并返回给客户端。另外,Impalad进程也会和Statusstore通信以确认哪些Impalad是可以正常工作的 - Statestore: 负责跟踪和检查Impalad健康状态的进程,由statestored进程表示;它负责处理Impalad的注册订阅,并且和各个Impalad进程保持心跳链接
- CLI: 提供给用户查询使用的命令行工具(Impala Shell使用python实现),同时Impala还提供了Hue,JDBC, ODBC使用接口
Impala没有使用MapReduce计算框架,而是使用与商用并行关系数据库中类似的分布式查询引擎,并且Impala的中间结果不写入磁盘,而是通过网络以流的形式传递,这大大降低了IO开销,因而Impala的查询速度非常快。但是Impala缺点也很明显,如对用户自定义函数支持不好、不支持Transforms、不支持查询期的容错等。
Apache Drill
Apache Drill是一个分布式的MPP SQL引擎,是开源版本的Google Dremel。它支持对本地文件、HDFS、HBASE等数据进行数据查询,也支持对如JSON等schema-free的数据进行查询,其架构如下图所示:
从上图可以看到,Drill的核心是DrillBit,它主要负责接收客户端的请求,处理查询,并将结果返回给客户端。 Drill的查询流程包括以下步骤:
- drill客户端发起查询,任意DrilBit都可以接受来自客户端的查询
- 收到请求的DrillBit成为驱动节点(Foreman),对查询进行分析优化生成执行计划,之后将执行计划划分成各个片段,并确定合适的节点来执行
- 各个节点执行查询片段,并将结果返回给驱动节点
- 驱动节点将结果返回给客户端
Presto
Presto是一个分布式的MPP查询引擎,支持多种数据源,包括Hive、RDBMS、Redis等,并且可以跨数据源查询。Presto的基本架构如下图所示:
主要组成部分包括:
- coodinator:用于解析查询SQL,生成执行计划,并分发给worker执行
- discovery server:worker上线后,向discovery server注册。coodinator分发任务前,需要向discovery server获取可以正常工作worker列表
- worker:具体执行任务的工作节点
Apache Phoenix
Apache Phoenix是一个运行在HBase上的SQL框架,其本质是用Java写的基于JDBC API操作HBase的开源SQL引擎,通过Phoenix可以像使用MySQL等关系型数据库一样操作HBase中的表。Apache Phoenix支持ACID事务功能的标准SQL,它将SQL编译成原生HBase的scan语句,其架构如下图所示:
从上图可以看到:
- Phoenix的JDBC driver是在HBase的client端
- Phoenix在HBase的RegionServer上
Apache Kylin
Apache Kylin是一个开源的分布式分析引擎,提供Hadoop/Spark之上的SQL查询接口及多维分析(OLAP)能力。Kylin的核心是预计算,即对可能用到的度量进行预计算,并将结果保存为Cube以便查询时直接访问。Kylin的架构如下图所示:
主要组成部分包括:
- 离线构建部分:根据元数据的定义,从数据源(如Hive)抽取数据,并通过MapReduce Job构建Cube,构建后的Cube保存在HBase中
- 在线查询部分:用户通过RESTful API、JDBC/ODBC等接口提交SQL,REST服务把SQL交给查询引擎处理。查询引擎解析SQL,生成逻辑执行计划,之后将其转化为基于Cube的物理执行计划,最后读取预计算生成的Cube并返回结果
Apache Flink
Apache Flink是一个面向分布式数据流处理和批量数据处理的开源计算平台,它能够基于同一个Flink运行时提供流处理和批处理两种类型应用的功能。区别于其他流处理系统,Flink作为流处理时,把输入数据流看做是无界的,而批处理被作为一种特殊的流处理,只是它的输入数据流被定义为有界的。
基于同一个Flink运行时(Flink Runtime),Flink分别提供了流处理和批处理API,为了实现API层流与批的统一,Flink提供了一种关系型API,即Table & SQL API。
Apache HAWQ
Apache HAWQ的全称是Hadoop With Query,是一个Hadoop原生的MPP SQL引擎。HAWQ能直接在HDFS上读写数据,而不需要connector,并支持ACID事务特性,其架构如下图所示:
主要组成部分包括:
- HAWQ master:负责处理客户端提交的SQL,解析优化后向集群Segment节点下发查询,合并从各Segemt节点返回的结果,并返回最终结果给客户端。HAWQ master内部由HAWQ Resource Manager,HAWQ Catalog Service,HAWQ Fault Tolerance Service,HAWQ Dispatcher等组件组成。HAWQ master还需要维护global system catalog,global system catalog是系统表的集合,其中包含了HAWQ集群的元数据信息
- HAWQ segment:集群的计算节点,本身不存储任何数据,所有数据都存储在HDFS上。HAWQ master在分派SQL请求给Segment时会附带相关的元数据信息,元数据信息包含了表的HDFS URL,Segment通过HDFS URL访问需要处理的数据
- PXF agent:PXF(Pivotal eXtension Framework)的服务。PXF是一个允许HAWQ访问外部系统数据的可扩展框架,其中内置了访问HDFS文件,HBase表以及Hive表的连接器,PXF还可以通过和HCatalog集成来直接访问Hive表
结束语
SQL-on-Hadoop系统经过了若干年的发展,已经有了很大的提高,但是目前各个系统仍然在不断完善提高,例如:
- 执行计划方面:更强的优化器
- 执行效率方面:支持code generation、vectorization等
- 存储格式方面:支持更高效列存等
未来也会出现更多技术、更多系统。本文主要介绍了目前几大开源的SQL-on-Hadoop系统及其架构,包括Hive、Spark、Presto、Drill等。
参考
Tutorial: SQL-on-Hadoop Systems
SQL 引擎年度总结
六大主流开源SQL引擎总结
apache hive
Hive架构
Spark SQL: Relational data processing in Spark
Impala架构和工作原理
Apache Drill
Apache Drill介绍
Presto实现原理和美团的使用实践
Phoenix overview
Apache kylin
Apache Flink
Flink原理与实现
HAWQ: A massively parallel processing SQL engine in hadoop
HAWQ技术解析-基本架构