Hive简介

数据仓库

数据仓库是一个支持管理决策的数据集合。数据仓库是面向主题的、集成的、随时间变化、信息本身相对稳定。数据仓库是所有操作环境和外部数据源的快照集合。

Hive

由Facebook开源用于解决海量结构化日志的数据统计工具。
Hive可以将结构化的数据文件映射为一张表,并提供类SQL查询功能。

Hive架构原理

Hive简介
组成
用户接口:Client
CLI(hive shell)、JDBC/ODBC(java访问hive)、WEBUI(浏览器访问hive)
元数据:Metastore
元数据包括:表名、表所属的数据库(默认是default)、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等;
默认存储在自带的derby数据库中。
Hadoop
使用HDFS进行存储,使用MapReduce进行计算。
驱动器:Driver
解析器(SQL Parser):将SQL字符串转换成抽象语法树AST,这一步一般都用第三方工具库完成,比如antlr;对AST进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误。
编译器(Physical Plan):将AST编译生成逻辑执行计划。
优化器(Query Optimizer):对逻辑执行计划进行优化。
执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。对于Hive来说,就是MR/Spark。
原理
Hive通过给用户提供的一系列交互接口,接收到用户的指令(SQL),使用自己的Driver,结合元数据(MetaStore),将这些指令翻译成MapReduce,提交到Hadoop中执行,最后,将执行返回的结果输出到用户交互接口。

Hive中基本数据类型

Hive数据类型 Java数据类型 长度 例子
TINYINT byte 1byte有符号整数 20
SMALINT short 2byte有符号整数 20
INT int 4byte有符号整数 20
BIGINT long 8byte有符号整数 20
BOOLEAN boolean 布尔类型 true或者false
FLOAT float 单精度浮点数 3.14159
DOUBLE double 双精度浮点数 3.14159
STRING(长度可变) string 字符系列。可以指定字符集。可以使用单引号或者双引号。 ‘now’ “for ”
TIMESTAMP 时间类型
BINARY 字节数组

DDL

创建表

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[(col_name data_type [COMMENT col_comment], …)]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], …)]
[CLUSTERED BY (col_name, col_name, …)
[sorted BY (col_name [ASC|DESC], …)] INTO num_buckets BUCKETS]
[ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION hdfs_path]
CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXISTS 选项来忽略这个异常。
EXTERNAL关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive创建内部表时,会将数据移动到数据仓库指定的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。
COMMENT:为表和列添加注释。
PARTITIONED BY创建分区表
CLUSTERED BY创建分桶表
SORTED BY不常用
ROW FORMAT DELIMITED
[FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char]
[MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
| SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, …)]

用户在建表的时候可以自定义SerDe或者使用自带的SerDe。如果没有指定ROW
FORMAT 或者ROW FORMAT DELIMITED,将会使用自带的SerDe。在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的SerDe,Hive通过SerDe确定表的具体的列的数据。
SerDe是Serialize/Deserilize的简称,目的是用于序列化和反序列化。
STORED AS指定存储文件类型
常用的存储文件类型:SEQUENCEFILE(二进制序列文件)、TEXTFILE(文本)、RCFILE(列式存储格式文件)。
如果文件数据是纯文本,可以使用STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCEFILE。
LOCATION :指定表在HDFS上的存储位置。
LIKE允许用户复制现有的表结构,但是不复制数据。

内部表(管理表)与外部表

外部表:Hive并非认为其完全拥有这份数据。删除该表并不会删除掉这份数据,不过描述表的元数据信息会被删除掉。
内部表:默认创建的表是内部表。Hive控制着数据的生命周期,当我们删除一个内部表时,Hive也会删除这个表中数据(元数据和表数据都会删除掉)。内部表不适合和其他工具共享数据。

分区表

Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。在查询时通过WHERE子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多。

把数据直接上传到分区目录上,让分区表和数据产生关联的三种方式

上传数据后修复

上传数据:dfs -put 本地路径 HDFS路径;
执行修复命令:msck repair table 表名;
再次查询数据:select * from 表名 where 条件;

上传数据后添加分区

上传数据: dfs -put 本地路径 HDFS路径;
执行添加分区: alter table 表名 add partition(month=‘202008’);
查询数据: select * from 表名 where month=‘202008’;

上传数据后load数据到分区

上传数据:load data local inpath ‘本地路径’ into table 表名 partition(month=‘202008’);
查询数据:select * from 表名 where month=‘202008’;

DML

语法:load data [local] inpath ‘路径’ [overwrite] into table 表名;
load data:表示加载数据
local:表示从本地加载数据到hive表(复制);否则从HDFS加载数据到hive表(移动)
inpath:表示加载数据的路径
overwrite into:表示覆盖表中已有数据,否则表示追加
into table:表示加载到哪张表

DQL

语法: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]

Like和Rlike

LIKE字句通过 % 代表零个或多个字符(任意个字符),_ 代表一个字符来指定匹配条件。
RLIKE子句通过Java的正则表达式来指定匹配条件。

join

Hive支持通常的SQL JOIN语句,但是只支持等值连接(等值连接是内连接的子集),不支持非等值连接。

分区排序(Distribute By)

Distribute By:类似MR中Partition,进行分区,结合Sort by使用。
对于Distribute by进行测试,一定要分配多Reduce进行处理,否则无法看到Distribute by的效果。

Cluster By

当Distribute by和Sorts by字段相同时,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外还兼具Sort by的功能。但是排序只能是倒序排序(DESC),不能指定排序规则为ASC或者DESC。

分桶

分区针对的是数据的存储路径;分桶针对的是数据文件。
分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区。
分桶是将数据集分解成更容易管理的若干部分的另一个技术。

分桶抽样查询

select * from 表名 tablesample(bucket 1 out of 4 on id);
TABLESAMPLE(BUCKET x OUT OF y) :
x表示从哪个bucket开始抽取,如果需要取多个桶,以后的桶号为当前桶号加上y。
例如,table总bucket数为4,tablesample(bucket 1 out of 2),表示总共抽取(4/2=)2个bucket的数据,抽取第1(x)个和第3(x+y)个bucket的数据。
注意:x的值必须小于等于y的值,否则报错:

其他常用查询函数

空字段赋值

NVL( string1, replace_with)
如果string1为NULL,则NVL函数返回replace_with的值,否则返回string1的值。

CASE WHEN

行转列

CONCAT(string A/col, string B/col…):返回输入字符串连接后的结果,支持任意个输入字符串;
CONCAT_WS(separator, str1, str2,…):它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;

列转行

EXPLODE(col):将Hive一列中复杂的array或者map结构拆分成多行。
LATERAL VIEW
用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias
解释:用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。

Hive简单调优

Fetch抓取

Hive中对某些情况的查询可以不必使用MapReduce计算。例如:SELECT * FROM 表名;在这种情况下,Hive可以简单地读取表对应的存储目录下的文件,然后输出查询结果到控制台。

本地模式

Hive的输入数据量是非常小的。在这种情况下,为查询触发执行任务消耗的时间可能会比实际job的执行时间要多的多。对于大多数这种情况,Hive可以通过本地模式在单台机器上处理所有的任务。对于小数据集,执行时间可以明显被缩短。

严格模式

可以防止用户执行那些可能意向不到的不好的影响的查询。
例如:
1.对于使用了order by语句的查询,要求必须使用limit语句。因为order by为了执行排序过程会将所有的结果数据分发到同一个Reducer中进行处理,强制要求用户增加这个LIMIT语句可以防止Reducer额外执行很长一段时间。
2.限制笛卡尔积的查询。