hive学习笔记——表的基本的操作

1、hive的数据加载方式

1.1、load data

这中方式一般用于初始化的时候

load data [local] inpath '...' [overwrite] into table t1 [partition(...)]
-- 如果有local是从linux磁盘加载,如果没带local是从hdfs的某个目录移动到hive中
-- 带上overwrite会覆盖掉表中原来的数据
-- partition 加载到指定分区

1.2、使用查询语句向表中插入数据

insert overwrite table t1 select * from t2;
--也可以不覆盖掉,直接导入,把关键词overwrite替换为into -- 对于分区表稍微复杂
insert overwrite table t2 partition(day=2) select * from t1;
--有一张大表,可以通过这种方式构建小表。但是这种方式在多个分区的情况下效率很低,会对原始表执行多次扫描。 --将一张大表拆开写入分区表的时候应该使用下面的语法
from t1
insert overwrite table t2 partition(day=2) select * where day=2
insert overwrite table t2 partition(day=3) select * where day=3
insert overwrite table t4 select * where day=4

1.3、动态分区的插入

如果分区很多的情况下,单独下插入语句是非常恐怖的事。

所谓的动态分区,指的是插入到目标表时,不指定分区值,仅指定分区字段,分区值是从原始表中取得的。

默认,hive是不支持动态分区插入的,如果不支持的话,可以设置hive.exec.dynamic.partition=true打开。

set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.mode=nonstrict;
set hive.exec.max.dynamic.partitions.pernode=1000;
insert overwrite table t2 partition(province,city) select ...,province,city from a;
--动态分区的字段一定位于其他各个字段的最后

也可以动态静态结合的使用

insert overwrite table t2 partition(province='beijing',city) select ...,province,city from a;
--前面指定了province的值的时候,在select中查不查province已经无所谓了(前面指定的值优先级高,但是不会对后面的查询结果进行过滤,就是说所有的province的值都会改为北京)

1.4、CTAS

使用单个查询语句创建表并加载数据(不能创建分区表,外部表,桶表)

create table ... as select

查询数据的时候允许创建一张表,语法如下

create table t3 as select id from t1 where id =1

1.5、导出数据

有两种方式:

(1)直接使用HDFS命令导出文件夹

(2)使用如下语法的hive

insert overwrite local directory 'localpath' select id from t1;

2、表查询

2.1、数据查询

表可以使用别名

select * from t1 e;

在select 和 where 子句中可以使用hive的内置函数和自定义函数。函数分为普通函数、聚合函数、表函数。其中表函数必须使用别名,不能在where语句中不能引用列别名。

2.2、表连接

hive只支持等值连接,即on子句中使用等号连接。

如果连接语句中有where子句,会先执行join子句,在执行where子句。

2.2.1、内连接

内连接指把符合条件的数据查询出来。

语句如下:

select * from user join job on user.id=job.user_id;
-- 等价于
select * from user , job on user.id=job.user_id;

2.2.2、左外连接

语句如下:

select * from user left outer join job on user.id=job.user_id;

2.2.3、右外连接

和左外连接类似,语句如下

select * from user right outer join job on user.id=job.user_id;

2.2.4、全外连接

语法如下

select * from user outer join job on user.id=job.user_id;

2.2.5、左半连接

老版本特有的功能,用来代替in 和 exist操作

语法如下:

select * from user left semi join job on user.id=job.user_id;
--语句相当于:
select * from user where user.id in (select user_id from job);

但是hive不支持in子句(新版本中已经支持in)

2.2.6、笛卡尔积

语句如下:

select * from user join job;  

2.2.7、join 与where的顺序

where 子句的执行顺序是位于join子句之后的。对比下列两个sql语句的输出

select * from user left join job on user.id=job.user_id where job.id=3;
select * from user left join (select * from job where id=3) job on user.id = job.user_id;

第一条语句无任何输出,第二条语句产生三条输出。

2.3、排序

hive支持 order by 和 sort by子句

当可能有多个reduce任务时,order by 是在一个 reduce 任务中进行排序;sort by 是在多个reduce 任务内部进行排序,每个reduce 任务自己排序,不管全局是否有排序。

distribute by 会与 sort by一起使用,目的是在sort 不用排序时 把相同的分类放到一个reduce中进行排序

*cluster by 是distribute by 和 sort by的缩写形式。

2.4、数据倾斜

数据不是均匀分布,在shuffle过程中,map向reduce分配数据的时候,分配的数据量不一样,导致执行时间不一样。

2.5、视图

*作用在于简化复杂查询

创建视图

create view user_view as select * from user where id=1;

3、hive参数

hive-default.xml中的参数

4、hive的文件格式

4.1、自定义hive的文件格式

create table t1(...) stored as textfile;
--缺点:占用空间比较大

sequencefile 是包含键值对的二进制的文件存储格式,支持压缩可以节约存储空间。是hadoop领域的标准文件格式,但是在hadoop之外无法使用。

rcfile 是列式文件存储格式,适合压缩处理。对于有成百上千的字段而言,RCFile 更加适合。

5、调优

5.1、本地模式

对于小文件处理,如果分发到各个节点处理,网络传输等因素效率很低。

对于小数据集,运行时设置SET mapred.job.tracker=local;可以使用本地方式运行,即在hive客户端执行,而不是提交到hadoop集群执行。因此速度更快。

5.2、map side agg

row format, storage format,serde

row foramt 用户指定row foramt(行分隔)

delimited 子句用户处理有分隔符的文件;

escaped by 子句用户普通处理分隔符;

null defined as 子句用户指定空如何显示,默认是'\N';

serde 子句用户指定serde;

stored as textfile 用于指定处处文件必须是普通文件;

stored as sequencefile 用户指定存储文件可以被压缩;

inputformat和outputformat用户指定inputformat和outputformat的名称;

stored as parquet 指定列格式 parquet存储格式;

stored by 用于创建非本地表,如hbase表等;

7、DML

7.1、Alter Table

--表重命名
Alter TABLE table_name RENAME To new_table_name;
--修改表属性
ALTER TABLE table_name SET TBLPROPERTIES table_properties;
--修改注释
ALTER TABLE table_name SET SERDEPROPERTIES serde_paoperties;
--添加SerDe
ALTER TABLE table_name SET SERDE serde_class_name [WITH SERDEPROPERTIES serde_properties];
ALTER TABLE table_name SET SERDEPROPERTIES serde_properties;
--修改表存储
ALTER TABLE table_name CLUSTERED BY(col_name,col_name...) [STORED BY(col_name...)] INTO num_buckets BUCKETS;

7.2、Alter Partition

7.2.1、Add Partitions

ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION partition_spec [LOCATION 'location1'] partition_spec [LOCATION 'location2'];

7.2.2、Dynamic Partition

7.2.3、Rename Partition

ALTER TABLE table_name Partition partition_spec RENAME TO PARTITION partition_spec;

7.2.4、Recover Partitions

MSCK REPAIR TABLE table_name;
--会把已经位于HDFS的分区目录中,但是在metastore中没有的分区信息,自动添加到metastore中。

7.2.5、Drop Partitions

ALTER TABLE table_name DROP [IF EXISTS] PARTITION partition_spec, PARTITION partition_spec;

如果分区有些保护,可以使用下面语句;

ALTER TABLE table_name DROP [IF EXISTS] PARTITION partition_spec IGNORE PROTECTION;

7.3、Alter Column

7.3.1、Change Column Name/Type/Position/Comment

ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name col_type [COMMENT col_comment] [FIRST|ALTER column_name];

修改语句只会影响metastore,不会影响原始数据。

7.3.2、Add/Replace Columns

7.4、Create/Drop/Alter View

创建视图

CREATE VIEW [IF NOT EXISTS] view_name [(column_name [COMMENT column_comment],...)] [COMMENT view_comment] [TBLPROPERTIES (property_name=property_value,...)] AS SELECT ...

视图仅是逻辑对象,在HDFS中没有存储。当基表改变时,视图定义不会改变,再次使用视图会报错。

--删除视图
DROP VIEW [IF EXISTS] view_name;
--修改视图定义
ALTER VIEW view_name AS select_statement;

7.5、Create/Drop Functions

7.6、Create/Drop/Grant/Revoke Roles and Privileges

7.7、Show

--显示数据库
SHOW DATABASES;
--显示表
SHOW TABLES [IN database_name];
--显示分区
SHOW PARTITIONS table_name;
--显示一部分分区
SHOW PARTITIONS [db_name].table_name [PARTITION(partition_desc)];
--显示表/分区扩展信息
SHOW TABLE EXTENDED [IN|FROM database_name] LIKE identifier_with_wildcards [PARTITION(partition_desc)];

7.8、Describe

7.9、Select

语法

[WITH CommonTableExpression (,CommonTableExpression)*]

SELECT [ALL|DISTINCT] select_expr,select_expr,...

FROM table_reference

[WHERE where_condition]

[GROUP BY col_list]

[[CLUSTER BY col_list] | [DISTRIBUTE BY col_list] [SORT BY col_list]]

[LIMIT number]

7.9.1、where 子句

where 子句必须是布尔值,可以支持子查询

7.9.2、all and distinct

select 子句中默认是all,可以不写。Distinct 是去重。

7.9.3、基于partition的查询

7.9.4、having 子句

having子句相当于子查询。

7.9.5、limit子句

返回指定数量的数据,数据是任意的。

7.10、使用正则

7.11、group by 子句

7.12、join子句

table_reference JOIN table_factor [join_condition]
| table_reference {LEFT | RIGHT | FULL} [OUTER] JOIN table_reference join_condition
|table_reference LEFT SEMI JOIN table_reference join_condition
|table_reference CROSS JOIN table_reference [join_condition]

不使用join,使用逗号分隔表,也会认为是join操作。

默认,每个join操作会产生一个 M/R job

驱动表

多表联合的时候,非驱动表会被缓存,也可以通过STREAMTABL指定驱动表

10、Types

10.1、符合类型

hive array、map、struct使用

struct:struct 内部的数据可以通过Dot(.)来访问

map(k-v对):访问指定域可以通过["指定域名称"]进行。map["key"]

array:array中的数据为相同类型,通过下标访问内部数据(起始位置0)

10.1.1、struct使用

建表:

create table student_test(id INT,info struct<name:STRING,age:INT>)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
COLLECTION ITEMS TERMINATED BY ':';
--FIELDS TERMINATED BY :字段之间的分隔符
--COLLECTION ITEMS TERMINATED BY :一个字段各item的分隔符

数据示例:

1,小李:12

加载数据

load data local  inpath 'data' into table student_test;

查询:

select info.age from student_test;

10.1.2、array的使用

创建表

create table array_table(name STRING,student_id_list array<INT>)
row format delimited
fields terminated by ','
collection items terminated by ':';

导入数据

load data local inpath 'data6' into table array_table;

查询

select student_id_list[] from array_table;

10.1.3、map使用

创建表

create table map_table(id STRING,pref map<string,int>)
row format delimited
fields terminated by '\t'
collection items terminated by ','
map keys terminated by ':';

导入数据

load data local inpath 'map_data' into table map_table;

查询

select perf['person'] from map_table;

11、ORC

ORC(optimized row columnar) 提供了更高效的方式存储hive数据。使用ORC,会提高读、写、处理数据的能力。

(1)每个task输出会产生一个文件,可以煎炒namenode的压力;

(2)支持datetime、decimal和复合类型;

(3)文件中可以存储轻量级的索引;

(4)支持数据类型的块压缩;

(5)使用多个RecordReader并发的读取相同的文件;

(6)ability to split files without scanning for markers;

(7)bound the amount of memory needed for reading or writing;

(8)metadata stored using Protocol Buffers,which allows addition and removal of fields;

12、CompressedStorage

压缩存储有时候可以获得更好的性能。

使用TextFile 存储时,可以使用GZIP或BZIP2进行压缩。操作如下:

CREATE TABLE raw(line STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n';
LOAD DATA LOCAL INPATH 'file.gz' INTO TABLE raw;

以上操作的缺点是hive在查下时不能 分割压缩文件,不能并行执行map。

更好的方式如下操作:

CREATE TABLE raw(line STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n';
CREATE TABLE raw_sequence(line STRING) STORED AS SEQUENCEFILE;
LOAD DATA LOCAL INPATH 'file.gz' INTO TABLE raw;
SET hive.exec.compress.output=true;
SET io.seqfile.compression.type=BLOCK; --NONE/RECORD/BLOCK
INSERT OVERWRITE TABLE raw_sequence SELECT * FROM raw;

把数据插入到另一张表,另一张表使用SequenceFile存储。

13、函数

13.1、常见函数

hive函数分为四大类:单行函数、聚合函数、表函数、分析函数。

在hive客户端输入show functions 中可以看到所有的函数。

查看函数的用法 show function function_name;

表函数:

explode()函数是把一个数组作为数据,输出时数组的每个元素作为单独一行。

示例:

select explode(array(1,23,4)) from dual;
select explode(map(1,11,2,22,4,44)) from dual;

*dual 是一个伪表,满足sql的语法select ... from ...;

*array是一个函数

posexplode()函数和explode()函数非常相似,增加的功能是返回结果带有位置信息,表示第几行。

parse_url_tuple()函数用户解析url信息。

示例:

select parse_url_tuple('http://www.test.com/a.html?key=k1&key2=k2#tag ','HOST','PATH','QUERY','QUERY:k1','QUERY:k2') from dual; 

12.2、自定义函数

12.2.1、自定义单行函数

(1)继承org.apache.hadoop.hive.ql.exec.UDF,覆盖其中的evaluate()方法,该方法的形参数量、类型,返回值类型,都不做限制。返回值只要是hive可以序列化的类型即可。

(2)打包成jar

(3)在hvie命令行下,执行命令ADD JAR ...jar;

(4)在hive命令行下,执行命令CREATE TEMPORARY FUNCTION xxx AS '函数全名称';

如果要删除函数,在hive命令行下,执行DROP TEMPORARY FUNCTION IF EXISTS xxx;

上一篇:学习迭代器实现C#异步编程——仿async/await(一)


下一篇:聊聊多线程那一些事儿 之 五 async.await深度剖析