Hive与Spark SQL

Hive与Spark SQL

开源社区在分布式计算框架基础上构建了支持SQL的引擎,典型的代表是MapReduce之上的Hive以及Spark之上的Spark SQL,这些数据分析引擎通常不支持标准SQL,而是对SQL进行了选择性支持,并进行了适当扩展,其中最主流的数据分析语言为HQL(Hive Query Language)。

一、SQL On Hadoop

目前构建在Hadoop之上的SQL引擎主要分为两类,基于计算引擎和基于MPP架构:
Hive与Spark SQL_第1张图片

  • 基于计算引擎:SQL引擎是在计算引擎基础上构建的,其基本原理是将SQL语句翻译成分布式应用程序,之后运行在集群中。典型的代表有构建在MapReduce之上的Hive和构建在Spark之上的Spark SQL。这类SQL引擎的特点是具有良好的扩展性和容错性,能够应对海量数据。
  • 基于MPP架构:SQL引擎是基于MPP架构构建的,其基本原理是将SQL翻译成可分布式执行的任务,采用Volcano风格的计算引擎并行处理这些任务,任务之间的数据流动和交换由专门的Exchange运算符完成。典型的代表由Impala等。这些SQL引擎具有良好的可扩展性,但容错性较差。

二、Hive架构

Hive是构建在分布式计算框架之上的SQL引擎,使用了Hadoop中的分布式存储系统HDFS/HBase和分布式计算框架MapReduce/Tez/Spark等。Hive是Hadoop生态系统中的重要部分,目前是应用最广泛的SQL On Hadoop解决方案。

1.Hive基本架构

Hive对外提供了三种访问方式,包括Web UI、CLI(Client Line Interface)和Thrift协议(支持JDBC/ODBC),而在Hive后端,主要由三个服务组件构成。

  • Driver(驱动器):Driver实现了SQL解析,生成逻辑计划、物理计划、查询优化与执行等,输入是SQL语句,输出为一系列分布式执行程序(可以为MapReduce、Spark等)。
  • Metastore:Hive Metastore是管理和存储元信息的服务,保存了数据库的基本信息以及数据表的定义等,为了能够可靠地保存这些元信息,Hive Metastore一般将元信息持久化到关系型数据库中,默认采用了嵌入式数据库Derby,用户可根据需要启用其他数据库MySQL。
  • Hadoop:Hive依赖于Hadoop,包括分布式文件系统HDFS、分布式资源管理系统YARN以及分布式计算引擎MapReduce。Hive中的数据表对应的数据存放在HDFS上,计算资源由YARN分配,而计算任务则来自MapReduce引擎。

2.Hive部署方式

  • 嵌入式模式:Metastore和数据库两个进程嵌入到Driver中,当Driver启动时会同时运行两个进程,一般用于测试。
  • 本地模式:Driver和Metastore运行在本地,而数据库(比如MySql)启动在一个共享节点上。
  • 远程模式:Metastore运行在单独一个节点上,被其他所有服务共享。使用Beeline、JDBC/ODBC、CLI和Thrift等方式访问Hive时,则采用的是该模式。这是一种常用于生产环境下的部署模式。

3.Hive查询引擎

Hive最初是构建在MapReduce计算引擎之上的,Hive逐步支持其他更高效的DAG计算引擎,包括Tez、Spark等,用户可个性化指定每个HQL的执行引擎。
相比于MapReduce计算引擎,新型DAG计算引擎采用以下优化机制让HQL具有更高的执行性能:

  • 避免借助分布式文件系统交换数据而减少不必要的网络和磁盘IO。
  • 将重复利用的数据缓存到内存中以加速读取效率。
  • 复用资源直到HQL运行结束(比如Spark、Executor一旦启用后不会释放,直到所有任务运行完成)

三、Spark SQL架构

Spark SQL是构建在分布式计算框架Spark之上的结构化数据处理引擎,不仅支持类HQL查询语言,也提供了一套结构化编程接口DataFrame/DataSet。Spark SQL是一个异构化数据处理引擎,支持多种数据源,包括HDFS(各种文件格式)、Hive、关系型数据库等,用户可以使用Spark SQL提供的类HQL语言和结构化编程结构处理这些数据源中的数据。

Hive与Spark SQL_第2张图片

Spark SQL基本架构主要由四层构成:
(1)用户接口层
Spark SQL提供了两套访问接口:

  • 类HQL语言:
    该语言兼容绝大部分HQL语法,支持CLI、JDBC/ODBC等访问方式。可以与Hive无缝集成,直接存取Hive Metastore中的数据库和数据表。
  • 结构化编程接口DataFrame/DataSet:
    SQL表达能力是有限的,对于复杂的数据分析,比如机器学习算法实现SQL很难胜任。为了解决SQL的缺点,Spark SQL引入了一套结构化编程接口DataFrame/DataSet,基于这套API,用户可灵活控制自己的计算逻辑,目前是Spark生态系统中最重要的编程接口。

(2) SQL引擎层:将查询语言翻译成最高效的分布式Spark程序
Spark SQL引擎层主要职责是将HQL或DataFrame/DataSet程序编译成可分布式运行的Spark程序,涉及生成逻辑计划、物理计划、查询优化与执行等。最重要的组件是查询优化器catalyst,确保生成最优化的分布式程序。

(3) 计算引擎层:Spark Core
SQL引擎层的输入是HQL或DataFrame/DataSet程序,而输出则是基于RDD模型的Sprk分布式计算程序,这些程序会直接运行在Spark计算引擎层。

(4) 存储层:支持各种数据源,包括HDFS、Hive、关系型数据库、HBase等
Spark SQL另一个强大之处是对数据源进行了抽象,内置了大量存储引擎的支持,包括HDFS(支持各种数据存储格式,包括行存储格式Text和Sequence File,列式存储格式Parquet和ORC等)、Hive、各种关系数据库等,用户也可以根据需要将特定数据存储引擎接入Spark SQL,进而利用其强大而灵活的引擎进行数据分析。

Spark SQL与Hive对比

Spark SQL与Hive均支持类SQL语言,能够很方便地处理海量数据,也有明显的区别。
Spark SQL与Hive对比如下表所示:

Spark SQL Hive
Spark SQL Hive
查询语言 类HQL与DataFrame/DataSet API HQL
元信息存储 Hive Metastore(如果处理的数据来自三方存储引擎,比如MySQL,则由对应引擎自己负责元信息存储) Hive Metastore
查询引擎 将查询语言翻译成最高效的分布式Spark程序 将HQL翻译成对应的分布式程序
分布式计算引擎 Spark Core MapReduce、Tez或Spark
分布式存储引擎 支持各种数据源,包括HDFS、Hive、关系型数据库、HBase等 主要是HDFS和HBase

四、HQL基本语法

1.数据表的创建

Hive数据表是多层级的,Hive中可以有多个数据库,每个数据库中可以存在多个数据表,每个数据表可进一步划分为多个分区或者数据桶,每个分区内部也可以有多个数据桶。
Hive与Spark SQL_第3张图片

Create [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
[(col_name data_type [COMMENT col_comment],...)]
[PARTITIONED BY (col_name data_type [COMMENT col_comment],...)]
[CLUSTERED BY (col_name,col_name,...) INTO num_buckets BUCKETS]
[
	[ROW FORMAT row_format]
	[STORED AS file_format]
]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value,...)]
[AS select_statement];

按照数据表语法定义顺序,依次解析各个关键字的含义:
1)数据表的类别。Hive数据表分为三类:临时表(TEMPORARY TABLE)、外部表(EXTERNAL TABLE)和受管理表(MANAGED TABLE),其区别如下:

  • 临时表:仅对当前session可见,一旦session退出,则该数据表将自动被删除。
  • 外部表:外部表的数据存储路径是用户定义的而非Hive默认存放位置,外部表被删除后,其对应的数据不会被清除(仅删除元数据)。
  • 受管理表:默认数据表的类型,这种表的数据受Hive管理的,与元信息的生命周期是一致的。

2)数据类型(data_type)。Hive提供了丰富的数据类型,不仅提供类似于关系型数据库中的基本数据类型,也提供了对高级数据类型(包括数据、映射表、结构体和联合体)。的支持,具体包括:

  • 基本数据类型,包括:TINYINT、SMALLINT、INT、BIGINT、BOOLEAN、FLOAT、DOUBLE、STRING、TIMESTAMP、DECIMAL、DATE、VARCHAR和CHAR等。
  • 数组(array):由相同数据类型的元素按一定顺序排列的集合。
  • 映射表(map):由key/value映射对组成的集合,key是value的索引。
  • 结构体(struct):由一系列具有相同类型或不同类型的数据构成的数据集合。
  • 联合体(union):将几种相同或不同类型的变量存放到同一段内存单元中。

3)分区表与分桶表。为了加速数据处理,数据表可进一步划分成更小的存储单位,即分区或分桶。

  • 分区表:数据表可以按照某一个或几个字段进一步划分成多个数据分区(使用语句"PARTITIONED BY col_name"),不同分区的数据将被存放在不同目录中。当一个查询语句只需要用到里面的若干个分区时,其他分区则可直接跳过扫描,大大节省不必要的磁盘IO。
  • 分桶表:数据表或数据分区可进一步按照某个字段分成若干个桶,比如语句"CLUSTERED BY(userid) into 32 BUCKETS"可将数据表按照userid这一字段分成32个桶,实际是按照公式hash_function(bucketing_column) mod num_buckets计算得到具体桶编号的,其中has_function与具体的数据类型有关。分桶表对倾斜数据表分析、数据采样和多表连接等场景有特殊优化。

4)行格式(row format)。该配置用于指定每行的数据格式,对行格式存储格式有意义,语法定义如下:

DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char] [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]

关键字含义如下:

  • FIELDS TERMINATED BY char:每行中不同字段之间的分隔符char。
  • COLLECTION ITEMS TERMINATED BY char:map,struct或array中每个元素之间的分割符char。
  • MAP KEYS TERMINATED BY char:map中key和value之间的分割符char。
  • LINES TERMINATED BY char:行分隔符char。

实例:创建一个名为person的数据表,由name(姓名)和score(课程成绩)两个字段构成,其中score数据类型为map,key为课程名,value是得分。

CREATE TABLE person(name STRING,score map<STRING,INT>)
ROW FORMAT DELIMITED 
FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':';

对应的数据存储格式为:

Tom 'Math':80,'Chinese':89,'English'95
Bob 'Chinese':60,'Math':80,'English'99

5)数据格式(file format)。Hive支持多种数据格式,包括:

  • TEXTFILE,文本文件,这是默认文件存储格式,用户可通过hive.default.fileformat修改默认值,可选值为:TextFile,SequenceFile,RCfile或ORC。
  • SEQUENCEFILE,二进制存储格式Sequence File;
  • RCFILE,列式存储格式;
  • ORC,优化的列式存储格式;
  • PARQUET,列式存储格式;
  • AVRO,带数据模式的存储格式。
  • INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname,通过自定义InputFormat和OutputFormat两个组件定义数据格式。

6)数据存放位置(HDFS path)。每个数据表对应的数据将被存在一个单独目录中,具体由配置参数hive.metastore.warehouse.dir指定,默认是/user/hive/warehouse/databasename.db/tablename/,比如数据库school中的表student存放路径则为:/user/hive/warehouse/school.db/student/中。

7)表属性。Hive允许用户为数据表增加任意表属性,每个表属性以key/value的形式存在,Hive也预定义了一些表属性,比如:

  • TBLPROPERTIES(“hbase.table.name”=“table_name”):用于Hive与Hbase集成,表示该Hive表对应的HBase表为table_name;
  • TBLPROPERTIES(“orc.compress”=“ZLIB”):用于标注ORC表的压缩格式,ZLIB为压缩算法。

2.Hive数据表的删除与修改

Hive提供了两种删除数据表的语法:

  • Drop Table,语法如下:
DROP TABLE [IF EXISTS] table_name[PURGE];

删除指定数据表的数据和元信息,其中数据将被移动到垃圾箱,除非设置了"PURGE"标志,则跳过垃圾箱直接永久清除。如果数据表是外表,则仅会清理元信息。

  • TRUNCATE TABLE,语法如下:
TRUNCATE TABLE table_name [PARTITION partition_spec];

删除指定数据表的全部数据或某个分区,默认情况下,删除的数据将被移动到垃圾箱。

3.数据查询语句

HQL数据查询语句的语法与标准SQL非常类似,具体如下:

[WITH CommonTableExpression (,CommonTableExpression)*]
SELECT [ALL | DISTINCT] select_expr,select_expr,...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list]
[ORDER BY col_list]
[CLUSTER BY col_list | [DISTRIBUTE BY col_list] [SORT BY col_list]]
[LIMIT number]

1) WITH CommonTableExpression (,CommonTableExpression):Hive提供了一种将子查询作为一个数据表的语法,叫做Common Table Expression(CTE),比如从表t中选出两种类型的数据,并合并在一起作为输出:

with t1 as (select * from t where key='5'),
t2 as (select * from t where key = '4')
select * from t1 union all select * from t2;

2) ORDER BY和CLUSTER BY:DISTRIBUTE BY语句能按照指定的字段或表达式对数据进行划分,输出到对应的Reduce Task或者文件中。CLUSTER BY等价于DISTRIBUTE BY与SORT BY组合。如下两条HQL语句等级:

SELECT col1,col2 FROM t1 CLUSTER BY coll
SELECT col1,col2 FROM t1 DISTRIBUTE BY coll SORT BY coll

实例:当数据量特别大,需要对最终结果进行排序时,建议采用DISTRIBUTE BY结合SORT BY语句,比如统计每个url对应的用户行为日志,并按照访问时间对结果排序,如果采用DISTRIBUTE B + SORT BY方式,HQL语句如下:

set mapreduce.job.reduces=2 
select url_id,log_time,log_type FROM behavior DISTRIBUTE BY url_id SORT BY user_id,log_time;

你可能感兴趣的:(笔记)