hive assert hive assert true_hive

hive assert hive assert true_hive assert_02

hive assert hive assert true_大数据_03



一、Hive数据类型

【1】基本数据类型

hive assert hive assert true_数据_04

【2】复杂类型

hive assert hive assert true_hive assert_05


二、运算符

运算符

描述

A+B

A和B 相加

A-B

A减去B

A*B

A和B 相乘

A/B

A除以B

A%B

A对B取余

A&B

A和B按位取与

A

B

A^B

A和B按位取异或

~A

A按位取反

操作符

描述

A=B

如果A等于B则返回TRUE,反之返回FALSE

A<=>B

如果A和B都为NULL,则返回TRUE,其他的和等号(=)操作符的结果一致,如果任一为NULL则结果为NULL

A<>B / A!=B

A或者B为NULL则返回NULL;如果A不等于B,则返回TRUE,反之返回FALSE

A<B

A或者B为NULL,则返回NULL;如果A小于B,则返回TRUE,反之返回FALSE

A<=B

A或者B为NULL,则返回NULL;如果A小于等于B,则返回TRUE,反之返回FALSE

A>B

A或者B为NULL,则返回NULL;如果A大于B,则返回TRUE,反之返回FALSE

A>=B

A或者B为NULL,则返回NULL;如果A大于等于B,则返回TRUE,反之返回FALSE

A [NOT] BETWEEN B AND C

如果A,B或者C任一为NULL,则结果为NULL。如果A的值大于等于B而且小于或等于C,则结果为TRUE,反之为FALSE。如果使用NOT关键字则可达到相反的效果

A IS NULL

如果A等于NULL,则返回TRUE,反之返回FALSE

A IS NOT NULL

如果A不等于NULL,则返回TRUE,反之返回FALSE

IN(数值1, 数值2)

使用 IN运算显示列表中的值

A [NOT] LIKE B

B是一个SQL下的简单正则表达式,如果A与其匹配的话,则返回TRUE;反之返回FALSE。B的表达式说明如下:‘x%’表示A必须以字母‘x’开头,‘%x’表示A必须以字母’x’结尾,而‘%x%’表示A包含有字母’x’,可以位于开头,结尾或者字符串中间。如果使用NOT关键字则可达到相反的效果

A RLIKE B / A REGEXP B

B是一个正则表达式,如果A与其匹配,则返回TRUE;反之返回FALSE。匹配使用的是JDK中的正则表达式接口实现的,因为正则也依据其中的规则。例如,正则表达式必须和整个字符串A相匹配,而不是只需与其字符串匹配

操作符

含义

AND

逻辑并

OR

逻辑或

NOT

逻辑否


三、Hive存储格式

Hive会为每个创建的数据库在HDFS上创建一个目录,该数据库的表会以子目录形式存储,表中的数据会以表目录下的文件形式存储。对于default数据库,默认的缺省数据库没有自己的目录,default数据库下的表默认存放在/user/hive/warehouse目录下

(1)TextFile

TextFile为默认格式,存储方式为行存储。数据不做压缩,磁盘开销大,数据解析开销大

(2)SequenceFile

SequenceFile是Hadoop API提供的一种二进制文件支持,其具有使用方便可分割可压缩的特点

SequenceFile支持三种压缩选择:NONE, RECORD, BLOCK。 Record压缩率低,一般建议使用BLOCK压缩

(3)RCFile

一种行列存储相结合的存储方式

(4)ORCFile

数据按照行分块,每个块按照列存储,其中每个块都存储有一个索引。hive给出的新格式,属于RCFILE的升级版,性能有大幅度提升,而且数据可以压缩存储,压缩快 快速列存取

(5)Parquet

Parquet也是一种行式存储,同时具有很好的压缩性能,同时可以减少大量的表扫描和反序列化的时间


四、Hive深入理解

【1】Hive内部表和外部表

Hive创建的表有两种类型:内部表和外部表

1)创建方式:

  • 内部表:create table student (id int,name string ,age int);
  • 外部表:create external table student (id int,name string ,age int) location “dir”;

2)加载数据方式:

  • load data local inpath ‘path’ into table table_name;
    我们都知道,加载HDFS上的数据操作就是对HDFS文件系统中的文件进行移动或者重命名,因此速度回非常的快
    Hive也不检查目录中的文件是否符合要加载的文件是否符合我们所声明的表的模式,如果有数据或者模式不匹配,我们只会在查询阶段进行检查

3)删除方式:

  • 内部表:drop table student; 数据和元数据会被一起进行删除
  • 外部表:drop table student; 只会删除元数据,不会删除数据

4)内部表和外部表的使用选择:

  • 大多数情况,他们的区别不明显,如果数据的所有处理都在 Hive 中进行,那么倾向于 选择内部表,但是如果 Hive 和其他工具要针对相同的数据集进行处理,外部表更合适
  • 使用外部表访问存储在 HDFS 上的初始数据,然后通过 Hive 转换数据并存到内部表中

【2】 Hive分区和分桶

为何分区分桶?

在Hive中有分区分桶的概念,在逻辑上分区表与未分区表没有区别,在物理上分区表会将数据按照分区键的列值存储在表目录的子目录中,目录名为“分区字段=值”。分区表可以让我们对表数据进行查询添加删除重命名清空等操作时在特定的区域(子目录)下操作数据,目的是为了减少扫描成本

分桶则是指定分桶表中的某一列,让该列数据按照哈希取模的方式随机、均匀地将数据分发到各个桶文件中
分桶改变了数据的存储方式,它会把哈希取模相同或者在某一区间的数据行放在同一个桶文件中,因此可以提高查询效率,同时也能让取样(Sampling)更高效


分区表(Hive的优化手段之一)

Hive分区又分为单值分区范围分区,单值分区又分为静态分区动态分区,我们着重了解一下单值分区

单值分区
单值分区根据插入时是否需要手动指定分区可以分为

  • 单值静态分区:导入数据时需要手动指定分区
  • 单值动态分区:导入数据时,系统可以动态判断目标分区

在使用静态分区的时候,我们首先要知道有什么分区类型,然后每个分区来进行数据的加载,这个操作过程比较麻烦;而动态分区不会有这些不必要的操作,动态分区可以根据查询得到的数据动态地分配到分区中去,动态分区与静态分区最大的区别是不指定分区目录,由系统自己进行过选择

单值分区表的建表方式有两种:直接定义分区字段create table like ,注意,单值分区表不能用 create
table as select 建表

而范围分区表只能通过直接定义分区字段 来建表

1)静态分区创建
直接在 partitioned by 后面跟上分区字段类型即可(分区字段不能和任何列重名)

create table student(id String,name String,age Int) partitioned by (year String,month String,day String)
row format delimited fields terminated by "\t";

2)静态分区写入

[1]覆盖写入
insert overwrite table student
partition (year='2020',month='04',day='17') 
select * from student_tmp;
 
[2]追加写入
insert into table student
partition (year='2020',month='04',day='17') 
select * from student_tmp;

3)动态分区创建

创建方式与静态分区表完全一样,一张表可同时被静态和动态分区字段分区,只是动态分区字段需要放在静态分区字段后面因为HDFS上的动态分区目录下不能包含静态分区的子目录

create table student(id String,name String,age Int) partitioned by (year String,month String,day String)
row format delimited fields terminated by "\t";

4)动态分区写入

静态分区键要用分区字段=值指定;动态分区只需要给出分区字段即可

# 开启动态分区参数设置
(1)开启动态分区功能(默认true,开启)
set hive.exec.dynamic.partition=true;
(2)设置为非严格模式(动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区)
set hive.exec.dynamic.partition.mode=nonstrict;
(3)在所有执行MR的节点上,最大一共可以创建多少个动态分区
set hive.exec.max.dynamic.partitions=1000;
(4)在每个执行MR的节点上,最大可以创建多少个动态分区。该参数需要根据实际的数据来设定。比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错
set hive.exec.max.dynamic.partitions.pernode=100;
(5)整个MR Job中,最大可以创建多少个HDFS文件
set hive.exec.max.created.files=100000;
(6)当有空分区生成时,是否抛出异常。一般不需要设置
hive.error.on.empty.partition=false;

# 创建中间结果表
create table student_tmp(id String,name String,age Int,year String,month String,day String)
row format delimited fields terminated by "\t";

# 从中间结果表查询数据动态插入到student表(查询的分区字段位置需要严格对应创建时的位置,不然就会出现对应不上的情况)
insert into table student
partition (year,month,day) 
select id,name,age,year,month,day from student_tmp

分桶表(Hive的优化手段之一)

分桶:是按照分桶字段的hash值去模除以分桶的个数,把数据分散进多个文件中,这些小文件称为桶

分桶的好处:
1)方便抽样 使取样(sampling)更高效,在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便
2)提高join查询效率 获得更高的查询处理效率,桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作,对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量

1)创建分桶表
分桶表的建表有两种方式:直接建表create table like

[1]直接建表
create table student (id String,name String,age Int)
clustered by (id) into 3 buckets
row format delimited fields terminated by "\t";

[2]create table like
create table student2 like student;

分桶键只能有一个分桶字段,表可以同时分区分桶,当表分区时,每个分区下都会有num_buckets 个桶。我们可以使用 sorted by 在桶内排序,排序字段分桶字段无需相同,ASC 为升序选项,DESC 为降序选项,默认排序方式是升序num_buckets 指定分桶个数,也就是表目录下小文件的个数

2)向分桶表写入数据
因为分桶表在创建的时候只会定义Scheme,且写入数据的时候不会自动进行分桶排序,需要人工先进行分桶排序后再写入数据,确保目标表中的数据和它定义的分布一致

往分桶表中插入数据有两种方式:

方式一:自动根据分桶数量设置Reduce数量(推荐使用)
我们需要确保Reduce数量和分桶数量一致,因此设置 set hive.enforce.bucketing = true; 属性,自动根据分桶数设置reduce数量

# 创建中间结果表
create table student_tmp (id String,name String,age Int)
row format delimited fields terminated by "\t";

# 从中间结果表查询数据插入student
insert into table student select * from student_tmp
方法二:将reducer个数设置为目标表的桶数,并在select语句中用 distribute by 分桶字段 对查询结果按目标表的分桶字段发送到对应的reduce(不推荐使用)
# 设置reduce数量
SET mapred.reduce.tasks = <num_buckets>; 
# 从中间结果表查询数据插入student
insert into table student select * from student_tmp distribute by id;

另外补充说明一下,在Hive中,ORC事务表必须进行分桶(为了提高效率),每个桶的文件大小应在100~200MB之间(ORC表压缩后的数据),通常做法是先分区后分桶


分桶抽样查询
对于非常大的数据集,有时用户需要使用的是一个具有代表性的查询结果而不是全部结果,Hive可以通过对表进行抽样来满足这个需求
抽样查询表student中的数据

select * from student tablesample(bucket 1 out of 4 on id);
注:tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y)

注意:👇

y必须是table总bucket数的倍数或者因子,hive根据y的大小,决定抽样的比例
例如,table总共分了4份,当y=2时,抽取(4/2=)2个bucket的数据,当y=8时,抽取(4/8=)1/2个bucket的数据

x表示从哪个bucket开始抽取。例如,table总bucket数为4,tablesample(bucket 1 out of 2),表示总共抽取(4/2=)2个bucket的数据,抽取第1、1+y个bucket的数据

注意: 0 < x + (n - 1) y <= 总桶数 ---> x<=y ,否则会报错如下👇
FAILED: SemanticException [Error 10061]: Numerator should not be bigger than denominator in sample clause for table stu_buck

分区表和分桶表的区别

分区表可以根据某些字段进行分区操作,细化数据管理,可以让部分查询更快
分桶表的原理和 MapReduce 编程中的 HashPartitioner 的原理类似

分区和分桶都是细化数据管理,但是分区表是手动添加分区,由于 Hive 是读模式,所以对添加进分区的数据不做模式校验,分桶表中的数据是按照某些分桶字段进行 hash 散列 形成的多个文件,所以数据的准确性也高很多

Hive分区的概念与传统关系型数据库分区不同

①.传统数据库的分区方式:就MySQL而言,分区独立存在于字段里,里面存储真实的数据,在数据进行插入的时候自动分配分区
②.Hive的分区方式:由于Hive实际是存储在HDFS上的抽象,Hive的一个分区名对应一个目录名,子分区名就是子目录名,并不是一个实际字段,所以我们在插入数据的时候指定分区,就是新建一个目录或者子目录,或者在原来目录的基础上来添加数据


五、Hive元数据与连接

【1】Hive可以将metadata存储在MySql里,metadata包含了表的属性、表的名称、表的列、分区及其属性以及表数据所在的目录等,所以所有HQL语句都会连接到MySql查询元数据信息 Hive将实际数据存储在HDFS,数据库和表在HDFS上的表现形式都是目录实际数据是文件

【2】Hive的metadata、metastore server(服务)、hiveserver2、beeline 之间的关系

  • ①.metadata :Hive元数据,即hive定义的表名,字段名,类型,分区,用户这些数据
  • ②.metastore server :hivestore服务端;主要提供将DDL,DML等语句转换为MapReduce,提交到HDFS中
  • ③.hiveserver2:hive服务端;提供hive服务,客户端可以通过beeline,JDBC等多种方式链接到Hive
  • ④.beeline:Hive客户端链接到Hive的一个工具,可以理解成mysql的客户端

【3】metaStore server 的3种开启方式:

  • ①.默认开启方式:
    没有配置metaStore的时候,每当开启bin/hive或者开启hiveServer2的时候,都会在内部启动一个metaStore 嵌入式服务,资源比较浪费,如果开启多个窗口,就会存在多个metaStore server
  • ②.local mataStore(本地)
    当metaStore和装载元数据的数据库(MySQL)在同一机器上时配置是此模式,
    开启metaStore服务就只需要开启一次就好,避免资源浪费
  • ③.Remote Metastore(远程)
    当metaStore和装载元数据的数据库(MySQL)不在同一机器上时配置是此模式,
    开启metaStore服务就只需要开启一次就好,避免资源浪费

【4】连接hive:
1) ./bin/hive 通过 hive 启动的hive服务,第一步会先启动metastore服务,然后在启动一个客户端连接到metastore。此时metastore服务端和客户端都在一台机器上,别的机器无法连接到metastore,所以也无法连接到hive,这种方式不常用,一直只用于调试环节

2) hive --service metastore & 通过hive --service metastore & 会启动一个 hive metastore服务默认的端口号为:9083,此时可以有多个hive客户端。此配置需要在在hive-site.xml中配置 hive.metastore.uris = thrift://ipxxx:9083 ,motestore 虽然能使Hive服务端和客户端分别部署到不同的节点,客户端不需要关注metadata的相关配置,但是metastore只能通过只能通过配置hive.metastore.uris的方式连接,无法通过jdbc的方式访问

3) ./bin/hiveserver2 + metastore + beeline

hiveserver2 会启动一个hive服务端默认端口为:10000,可以通过beeline,jdbc,odbc的方式链接到hive。hiveserver2启动的时候会先检查有没有配置 hive.metastore.uris,如果没有会先启动一个metastore服务,然后在启动hiveserver2,如果有配置hive.metastore.uris,会连接到远程的metastore服务。这种方式是最常用的。部署在图如下:

都看到这里了,点赞评论一下吧!!!

hive assert hive assert true_hive_06

点击查看👇

【Hive】Hive入门解析(四)