HIVE-表操作基础知识

上一份工作对数据的时效性要求较高,且公司有较为完善的数据平台,所以hive没怎么写过,现在的新工作需要大量的用底层数据(仓库未搭建),物流行业的底层数据质量相对较差,需要做大量清洗工作,又重新学习了一下hive,大致的总结了一下。

一、HIVE建表语句

--中括号里面的都可以省略
CREATE [EXTERNAL] table [IF NOT EXISTS] table name
[(col_name data_type [COMMENT col_comment],..]
[COMMENT table_name]
[PARTITION BY (col_name data_type [COMMENT col_comment],..]
[CLUSTERED BY (col1,col2)
[SORTED BY (col_name [ASC|DESC],,,)] INTO num_buckets BUCKETS]
[ROW FORMAT row_format]
[FIELDS TERMINATED BY '']
[STORED as file format]
[LOCATION hdfs_path]


说明:
1、CREATE table创建一个指定名字的表,如果相同名字的表已经存在,则抛出异常,用户可以用IF NOT EXIES来忽略这个异常
2、EXTERNAL关键字可以让用户建立一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION)
HIVE创建内部表时,会将数据移动到数据仓库指向的路径,若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。
在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据
3、like允许用户复制现有的表结构,但是不复制结构
CREATE [EXTERNAL] table [IF NOT EXISTS] [db_name.]table name like existing_table;
4、
ROW FORMAT delimited  这里采用内置分隔符
[fields terminated by char] 字段间用什么分隔
[collection items terminated by '-'] 集合采用什么分隔
[map keys terminated by ':']; 中间的键值对用什么分隔
[lines terminated by char] serde serde_name
[with serdeproperties 
(property_name=property_value,property_name=property_value,....)]
hive建表时候默认的分隔符是'\001',如果load时候文件分隔符不是'\001',程序不会报错,返回的都是null
serde 是Seralize的简称,目的是用于序列化和反序列化
hive读取文件机制,首先调用InputFormat(默认TextInputformat),返回一条条记录(默认是一行对应一条记录),然后调用Serde(默认LazySimpleSerde)
的Deserializer,将一条记录切分为各个字段(默认'\001')

hive写文件机制,将Row写入文件时,主要调用OutputFormat\Serde的Seriliazer,顺序与读取相反

5、在hive SELECT查询中一般会扫描整个表的内容,会消耗很多时间做没必要的工作,有时候只需要扫描表中的一部分数据,所以会用到partition分区数据
分区表指的是在创建表时指定的partition的分区空间,一个表可以拥有一个或多个分区,每个分区以文件夹的形式单独存在表文件夹的目录中。表和列名不区分大小.分区是以字段的形式在表结构中存在,通过describe table命令可以查看到字段存在,但是该字段不存放实际的数据内容仅仅是分区的表示
---------------------------------------------------------------------------------------------------
如果数据在linux上,--load加载数据
load DATA local INPATH '/root/hivedata/students.txt' INTO TABLE STUDENT
这样加载数据


--hive支持的数据类型可以看官方wiki(https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types)
--支持Java的数据类型


---------------------------------------------------------------------------------------------------
二、建立分桶表
--首先要开启桶表功能
--分桶表创建之前,分桶表的字段必须是已经创建的字段
--桶表不能用load data命令,load data命令本身不执行MR程序,load本身相当于hive帮我们执行hadoop fs -put
set hive.enforce.bucketing = true;
set mapreduce.job.reduce=4; --分成几个桶
--固定结构
create [external] table [IF NOT EXISTS] table name 
[COL_NAME DATA_TYPE [COMMENT col_comment]]
[comment table_comment]
[partitioned by(ds string,)] -分区
[clustered by (col1,col2) --哪一列分桶操作
[sorted by (col_name [ASC|DESC],,,)] INTO NUM_BUCKETS BUCKETS] --分成几个桶
row format.....


--例子
create table stu_bruck(sno int,sname string)
clustered by sno
into 4 buckets
row_format delimited
fields TERMINATED BY ',';




--分桶表插入数据,查询时执行了MR程序
insert overwrite table stu_buck
select * from table cluster by (sno)




--CLUSTERED BY INTO NUM_BUCKETS BUCKETS
对于每一个表或者分区,hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。hive也是针对某一列进行桶的组织。hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。
做成桶表主要有2个好处
(1)获得更高的查询效率。桶为表加上了额外的结构,hive在处理有些查询时能利用这个结。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用MAP端连接(Map-side join)高效的实现。比如join操作。对于join操作两个表有一个相同的列,如果对这两个表都进行了桶操作,那么将保存先沟通列值的桶就行join操作就可以大大减少join的数据量。
(2)使取样更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一部分数据上进行查询,会带来很多方便

--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
三、修改表:
1、增加分区:
ALTER TABLE table_name ADD PARTITION (dt='20180101') location 
'/user/hadoop/warehouse/table_name/dt='20180101'';一次添加一个分区


ALTER TABLE table_name ADD PARTITION (ds='20180101',country='US') location
'/part/to/us/part080101'PARTITION(ds='20180101',country=US') location
'/part/to/us/part080102';  一次添加多个分区


2、删除分区
ALTER TABLE table_name DROP IF EXISTS PARTITION (ds='20180101');
ALTER TABLE table_name DROP IF EXISTS PARTITION (ds='20180101',country='US');




3、修改分区
ALTER TABLE table_name PARTITION (dt='20180101') RENAME TO PARTITION (dt='20180102');


4、添加列
ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name STRING);
注:ADD代表新增一个字段,新增字段位置在所有列后面(分区前)
replace则是表示替换表中所有字段

5、修改列
table_name(a int,b int,c int);


ALTER TABLE table_name CHANGE a a1 int;  --a改成a1


ALTER TABLE table_name CHANGE a a1 string AFTER b;  --a改成a1,b列后面


ALTER TABLE table_name CHANGE a a1 int FIRST;     --修改后放在第一列




6、表重命名
ALTER TABLE table_name RENAME TO new_table_name






-----------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
四、显示命令
show tables;
显示当前数据库的所有表


show databases|schemeas;
显示表分区信息,不是分区表执行报错


show functions;
显示当前版本hive支持的所有方法


desc extended table_name;
查看表信息


desc formatted table_name;
查看表信息(格式化美观)


describe database database_name;
查看数据库相关信息




五、DML操作
2.1 load
在将数据加载到表中时,hive不会进行任何转换,加载操作是将数据文件移动到与hive表对应的位置的纯复制/移动操作。
语法结构
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO
TABLE tablename [PARTITION (partcol1=val1,partcol2=val2.....)]

说明
1、filepath
相对路径:例如:project/datal
绝对路径:例如:/user/hive/project/datal
完整url,例如:hdfs://namenode:9000/user/hive/project/datal


六、insert语法 
hive中主要结合select查询语句使用,将查询结果插入表中,例:
例: insert overwrite table test_table
select * from test cluster by (sno)
需要保证查询结果列的数目和需要插入数据表的列数目一致。
如果查询出来的数据类型和插入表格对应的列数据类型不一致,将会进行转换,但是不能保证转换一定成功,转换失败的数据将会为NULL

可以将一个表查询出来的结果插入到原表中,结果相当于自我复制了一份数据。

multi inserts多重插入,主要是从同一个表取不同数据插入不同表里
from source_table
insert overwrite table tablename1 [partition (partcol1=val1,partcol2=val2)]
select_statement1
inser  overwrite table tablename2 [partition (partcol1=val1,partcol2=val2)]
select_statement2

Dynamic partition inserts 动态分区插入:
insert overwrite table table_name partition (partcol1[=val1],partcol2[=val2].......)
select_statement FROM from_statement
动态分区是通过位置来对应分区值的.原始表select出来的值和输出partition的值的关系仅仅是通过位置来确定的,和名字没有关系,名字可以不一样的

动态分区插入语法
set hive.exec.dynamic.partition=true; #是否开启动态分区功能,默认FALSE
set hive.exec.dynamic.partition.mode=nonstrict; #动态分区的模式,默认strict,表示必须至少指定一个分区为静态分区,nonstrict模式允许所有的分区字段都可以使用动态分区

七、导出表数据
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 select ... from ...
multiple inserts:
FROM from_statement
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 select_statement1
[INSERT OVERWRITE [LOCAL] DIRECTORY directory2 select_statement2].....
数据写入到文件系统时进行文本序列化,且每列用^A来区分,\n为换行符。




八、cluster by、sort by、distribute by
说明:
1、order by会对输入做全局排序,因此只有一个reducer,会导致当输入规模较大时,需要较长时间计算


2、sort by不是全局排序,其在数据进入reducer前完成排序,因此,如果用sortby就行排序,并且设置
mapred.reduce.tasks>1,则sort by只保证每个reducer的输出有序,不保证全局有序。


3、distribute by(字段)根据指定字段讲数据分到不同的reducer,分发算法是hash散列。


4、Cluster by(字段)除了具有distribute by的功能外,还会对该字段进行排序。


如果distribute和sort的字段是同一个时,此时,cluster by=distribute by+sort by
1、#指定开启分桶
set hive.enforce.bucketing=true;
set mapreduce.job.reduce=4;


select * from ods.base cluster by (id);--这样就会分为4桶


九、hive join
HIVE中除了支持和传统数据库中一样的内关联、左关联、右关联、全关联,还支持LEFT SEMI JOIN和CROSS JOIN,单这种join也可以用前面的代替。

HIVE支持等值连接,不支持非等值连接,因为非等值连接非常难转化到map/reduce任务,另外,hive支持2个以上表之间的join。

join时,每次map/reduce任务的逻辑
reducer会缓存join序列中除了最后一个表的所有表的记录,再通过最后一个将结果序列化到文件系统。这一实现有助于在reduce端减少内存的使用量。实践中,应该把最大的那个表写在最后(否则会因为缓存浪费大量内存)


left,right和full outer 关键字用于处理join中空记录的情况
join发生在where字句之前


left semi join 
例子:a表只有id,name两个字段
select * from a left semi join b on a.id=b,id;
select a.id,a.name from a join b on a.id=b.id;


cross join 

返回两个表的笛卡尔积结果,不需要指定关联键(注:数据量较大,慎用)

猜你喜欢

转载自blog.csdn.net/huobumingbai1234/article/details/80861416