03 hive 的表操作、数据加载、导出

教程 阿布都的都 ⋅ 于 2023-01-06 19:16:04 ⋅ 1156 阅读

1 表SQL操作

1.1 通过select数据集创建表

--通过select数据集创建表语法格式
create table table_name [stored as orc]  
as
select  ......

只能是内部表,不支持分区,分桶

示例:

--创建内部表inner_test1
create table inner_test1 as
select word,num from word_table;
--查看
select count(1) from inner_test1;

file

1.2 复制一个空表

--只复制表结构,不复制表数据
CREATE TABLE empty_key_value_store LIKE key_value_store;

create table inner_test2 like inner_test1;

file

1.3 显示表列表

--显示所有表
SHOW TABLES;
--按条件(正则表达式)显示表
SHOW TABLES '.*s';
show tables 'user*';
-- 最通用的写法
show tables like '*user*';
-- 显示函数
show fuctions like '*count*';

file

1.4 删除表

--删除表
DROP TABLE [IF EXISTS] table_name [PURGE]; 

说明:

​ 1)对于内部表来说,删除表的操作的本质是删除表的元数据,然后hadoop fs -rm(将表数据挪到回收站目录, .Trash/Current)。

​ 2)如果增加PURGE则不进回收站数据直接删除,不能恢复;

​ 3)对外部表而言只删除元数据, 不删除数据目录,加PURGE也不删。

示例:

drop table inner_test1;

file

1.5 清除表(只针对内部表)

--清除表
TRUNCATE TABLE table_name [PARTITION partition_spec];

说明:

​ 1)可以删除表和删除分区数据,和drop的区别是不删除元数据(表结构),只删除数据,外部表是不能truncate操作的。

​ 2)外部表不支持使用TRUNCATE语句。

file

1.6 常用修改表操作

file

1.6.1 改表名

--改表名
ALTER TABLE table_name RENAME TO new_table_name;
--内部表修改表名
ALTER TABLE user_info RENAME TO user_info_2;
--外部表修改表名
alter table ext_test rename to ext_test_2;

说明:

​ 内部表修改了表名之后,表对应的存储文件地址也跟着改,相当于作了HDFS的目录重命名。

​ 外部表不会改对应的location地址。

内部表重命名

ALTER TABLE inner_test RENAME TO inner_test_c;

hdfs 作了目录重命名

file

-----------------------------------

外部表重命名

ALTER TABLE ext_test RENAME TO ext_test_c;

file

1.6.2 修改表属性

ALTER TABLE table_name SET TBLPROPERTIES table_properties;

示例:

alter table ext_test set tblproperties ('comment' = 'EXTERNAL table a!');

file

1.6.3 增加表分区

​ 内部表增加表分区,自动创建目录。

​ 外部表增加表分区,自动创建目录。

示例:

1)创建分区表:

-- 分区表外部表
CREATE EXTERNAL TABLE ext_task(
word STRING,
num INT
)
PARTITIONED BY (taskname STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
LOCATION '/user/cz45/hive45/ext_task';
-- 分区表内部表
CREATE TABLE inner_task(
word STRING,
num INT
)
PARTITIONED BY (taskname STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

2)添加表分区

-- 分区表外部表添加分区
alter table ext_task add IF NOT EXISTS partition(taskname='wordcount') location 'wordcount';
alter table ext_task add IF NOT EXISTS partition(taskname='maxword') location 'maxword';
alter table ext_task add IF NOT EXISTS partition(taskname='sortword') location 'sortword';
-- 分区表内部表添加分区
alter table inner_task add IF NOT EXISTS partition(taskname='wordcount') location 'wordcount';
alter table inner_task add IF NOT EXISTS partition(taskname='maxword') location 'maxword';
alter table inner_task add IF NOT EXISTS partition(taskname='sortword') location 'sortword';

3)查看表的元数据和表分区元数据

-- 查询具体表的分区目录
select t1.`NAME`, t2.TBL_NAME,t4.PART_NAME, t3.LOCATION from DBS t1, TBLS t2 , SDS t3 , `PARTITIONS` t4 
where t1.DB_ID=t2.DB_ID and 
            t4.SD_ID = t3.SD_ID AND 
            t2.TBL_ID = t4.TBL_ID and 
            t1.`NAME` = 'dbname' AND 
      t2.TBL_NAME like '%task' 
UNION
-- 查询具体表的目录
select t1.`NAME`, t2.TBL_NAME,'null', t3.LOCATION from DBS t1, TBLS t2 , SDS t3 
where t1.DB_ID=t2.DB_ID and 
            t2.SD_ID = t3.SD_ID AND
            t1.`NAME` = 'dbname' AND 
      t2.TBL_NAME like '%task' ;

1.6.4 删除分区

--删除表分区的语法格式
ALTER TABLE table_name DROP [IF EXISTS] PARTITION partition_spec[, PARTITION partition_spec, ...];

说明:

​ 内部表删除分区,同时删除分区对应的目录。

​ 外部表删除分区不删除分区对应的目录。

示例:

-- 内部表删除分区
alter table inner_task DROP IF EXISTS partition(taskname='sortword');
-- 外部表删除分区
alter table ext_task DROP IF EXISTS partition(taskname='sortword');

外部表删除:sortword 分区

元数据删除

file

数据没删除:

file

1.6.5 修改表或分区的路径

--修改表或分区路径的语法格式
ALTER TABLE table_name [PARTITION partition_spec] SET LOCATION "new location";

说明:

​ 内部表修改分区路径,元数据修改,但hdfs目录没有创建,等导入数据时创建,或者自己主动创建。

​ 外部表修改分区路径,元数据修改,但hdfs目录没有创建,等导入数据时创建,或者自己主动创建。

示例:

--内部表修改分区路径
alter table inner_task PARTITION  (taskname='wordcount') set location "hdfs://ns1/hive/warehouse/cz45.db/inner_task/wordcount1";
--外部表修改分区路径
alter table ext_task PARTITION  (taskname='wordcount') set location "hdfs://ns1/user/panniu/hive/ext_task/wordcount1";

内部表:

修改分区路径:

file

导入数据后

file

file

-----------------------------

外部表:

修改分区路径:

file

导入数据后:

file

结论:无论是外部表还是内部表,修改分区路径,需要自己手动创建路径,或者等导入数据时创建。

1.6.6 分区重命名

--分区重命名语法格式
ALTER TABLE table_name PARTITION partition_spec RENAME TO PARTITION partition_spec;

说明:

​ 如果是内部表,分区重命名,分区对应的地址也会跟着改变,外部表不会。

示例:

--内部表分区重命名会改变分区对应的地址
alter table inner_task partition (taskname='maxword') rename to partition (taskname='maxword01');
--外部表分区重命名不会改变分区对应的地址
alter table ext_task partition (taskname='maxword') rename to partition (taskname='maxword01');

内部表修改分区名称,hdfs目录也修改

file

file

外部表修改分区名称,只修改元数据

file

file

insert into table ext_task partition(taskname='maxword01')

select word,num from ext_test_c;

maxword01分区导入数据后

file

1.6.7 增加表字段

--增加表字段、使用新列集合替换现有数据列的语法格式
ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...)

说明:

​ 1)ADD COLUMNS 可以在表列的最后和分区字段前面增加字段。

示例:

1)增加表字段

alter table ext_test_c add columns (test_col string);

--------------------

-- 添加新字段

alter table ext_test_c add columns (col_new string);

-- 导入数据

insert into table ext_test_c

select word,num, 'aaa' from ext_task where taskname='maxword01';

file

1.6.8 修改表字段

--语法格式
ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name] 

示例:

alter table ext_test_c CHANGE  COLUMN col_new col_new2 string;

file

2 视图操作

file

和关系型数据库一样,Hive中也提供了视图的功能,注意Hive中视图的特性,和关系型数据库中的稍有区别:

只有逻辑视图,没有物化视图;

视图只能查询,不能Load/Insert/Update/Delete数据; alter view 和重建效果一致。

视图在创建时候,只是保存了一份元数据,在hdfs中没有体现,当查询视图的时候,才开始执行视图对应的那些子查询,如果子查询比较简单,不会生成MapReduce任务;

--创建视图的语法格式
CREATE VIEW [IF NOT EXISTS] [db_name.]view_name [(column_name [COMMENT column_comment], ...) ]
[COMMENT view_comment]
[TBLPROPERTIES (property_name = property_value, ...)]
AS SELECT ...;
--查看列表
show tables;
-- 查看创建视图的语句
show create table xxx;

说明:

​ 1)视图列和类型可以不指定,如果不指定则有select集合列名和类型决定。

示例:

--原来的SQL, 查询出最多国家的名称和人数
select t1.nn, t2.country from
(select max(a.n) as nn from (
select count(1) n,country from user_install_status_limit group by country
) a) t1
inner join 
(select count(1) as n, country from user_install_status_limit group by country) t2 
on t1.nn = t2.n;    
-- 重复的SQL创建视图
create view tt_country_view
as 
select count(1) n,country from user_install_status_limit group by country;
-- 重复的SQL改成视图,结果不变
select t1.maxn, t2.country from
(select max(n) as maxn from tt_country_view
) t1
inner join 
tt_country_view t2 
on t1.maxn = t2.n;  

结论: 无论 使用视图还是不使用视图,执行的任务数不变。主要是为了简化SQL的编写;

file

3 数据加载

3.1 load 加载数据

file

如果想用:就用hdfsload, 先添加分区,再导入数据

3.1.1 语法

--load数据加载语法格式
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]

说明:

​ 1)hive 的数据加载不会对本地数据文件做任何处理,只是将文件或目录中的所有文件拷贝到表定义的数据目录。

​ 2)filepath 可以是目录,但该目录下不能包含子目录。

​ 3)指定LOCAL本地文件上传,如果没有指定LOCAL,则使用表一样的文件系统 (本地文件不删除)。

​ 4)文件加载hive没有做严格校验,文件格式和压缩选项等匹配需要用户自己保证。

​ 5)分区表要指定具体加载数据分区。

​ 6)如果指定OVERWRITE会覆盖相应表数据或分区数据,相当于 rm 原有目录数据,然后上传新数据文件

HDFS执行MV操作。

-- 以覆盖或追加的方式 , 从linux本地 copy文件到表或表分区里
LOAD DATA LOCAL INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
--以覆盖或追加的方式 , 从hdfs move 文件到表或表分区里
LOAD DATA INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]

filepath目录下不能包含子目录

file

3.1.2 将hdfs中的文件load到表中(move)

需要把 \ext_task 创建出来****

-- 分区表外部表
CREATE EXTERNAL TABLE ext_task(
word STRING,
num INT
)
PARTITIONED BY (taskname STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
LOCATION '/user/panniu/hive30/ext_task';

如果想得到

partition: wordcount01 → /user/panniu/hive31/ext_task/wordcount01

1)先创建分区wordcount01

2)再load数据到表分区wordcount01中

-- 创建分区

alter table ext_task add if not exists partition (taskname='wordcount01') location 'wordcount01';

-- 造数据 上传到 hdfs://ns1/user/panniu/hive26/demo

file

-- 导入数据

load data INPATH 'hdfs://ns1/user/panniu/hive26/demo' overwrite into table ext_task PARTITION (taskname='wordcount01');

数据导入到了 表的 wordcount01分区

file

hdfs://ns1/user/panniu/hive26/demo 这个目录,已经mv走了

file

file

如果没有创建分区 wordcount02, load时,会自动创建分区目录,目录名为taskname=wordcount02

partition: wordcount02 → /user/panniu/hive/ext_task/taskname=wordcount02

load data INPATH 'hdfs://ns1/user/panniu/hive/data123/word' overwrite into table ext_task PARTITION (taskname='wordcount02');

file

3.1.3 将本地文件load到表中

--添加partition
alter table ext_task add IF NOT EXISTS partition(taskname='wordcount04') location 'wordcount04';
--本地文件load到表中,相当于将本地文件上传到hdfs中,本地文件不删除
load data local INPATH '/home/panniu/hive_test/word' overwrite into table ext_task PARTITION (taskname='wordcount04'); 

file

如果从本地通过load加载数据到hive表,如果用的是into 则分区目录是什么,就将数据放到哪个目录下

但是如果从本地通过load加载数据到hive表,用的是overwrite into ,除非分区目录是分区字段=具体的值(例如age=10),否侧数据不会上传到我们指定的分区目录中,而是hive帮我们新建一个分区目录(分区字段=具体的值)用来存放数据

如果是 从hdfs通过load加载数据到hive表,不管你用的是into还是overwrite into,全部将数据方式指定的分区目录下

taskname=wordcount04

-- 添加分区

alter table ext_task add IF NOT EXISTS partition(taskname='wordcount04') location 'wordcount04';

-- 导入数据

load data local INPATH '/home/panniu/hive_test/ext' overwrite into table ext_task PARTITION (taskname='wordcount04');

file

元数据也换了

file

3.2 通过select加载数据

file

--通过select,将select数据覆盖表或分区的语法格式
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] 
select_statement1 FROM from_statement;
--通过select,将select数据追加到表或分区的语法格式
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] 
select_statement1 FROM from_statement;

说明:

​ 1)当加了 IF NOT EXISTS,如果存在分区就跳过下面的select语句。

​ 2)INSERT OVERWRITE 会覆盖表或分区数据,但覆盖分区时增加IF NOT EXISTS,如果分区已经存在则不会覆盖。

​ 3) INSERT INTO 向表或分区追加数据,不影响历史数据。


示例:

1)将select的数据覆盖到表分区

--添加分区
alter table ext_task add IF NOT EXISTS partition(taskname='wordcount05') location 'wordcount05';
--导入数据
insert overwrite table ext_task partition(taskname='wordcount05')
select
word,
num
from ext_task
where taskname='wordcount01';

file

2)通过select,将select数据追加到表分区

insert into table ext_task partition(taskname='wordcount05') 
select
word,
num
from ext_task
where taskname='wordcount01';

file

3.3 动态分区

file

-- 学生表
CREATE TABLE student(
id int,
name string,
age int
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
-- 学生表数据
1   name1   12
2   name2   12
3   name3   13
4   name4   13
5   name5   14
6   name6   14
7   name7   15
8   name8   15
-- 学生分区表
CREATE TABLE student_dyna(
id int,
name string
)
partitioned by (age int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
-- 需求:把学生表的数据导入的学生分区表中
-- 静态分区导入  适合增量数据的处理
-- 添加12岁的分区,导入12岁数据
alter table student_dyna add IF NOT EXISTS partition(age=12) location '12';
insert overwrite table student_dyna partition(age=12)  
select id,name from student where age=12;
-- 添加13岁的分区,导入13岁数据
alter table student_dyna add IF NOT EXISTS partition(age=13) location '13';
insert overwrite table student_dyna partition(age=13)  
select id,name from student where age=13;
-- 添加14岁的分区,导入14岁数据
alter table student_dyna add IF NOT EXISTS partition(age=14) location '14';
insert overwrite table student_dyna partition(age=14)  
select id,name from student where age=14;
-- 添加15岁的分区,导入15岁数据
alter table student_dyna add IF NOT EXISTS partition(age=15) location '15';
insert overwrite table student_dyna partition(age=15)  
select id,name from student where age=15;
------------------------
-- 历史数据导入,不适合静态分区,需要要用动态分区
-- hive默认不开启动态分区
--开启动态分区
set hive.exec.dynamic.partition=true;  
--这个属性默认是strict,即限制模式,strict是避免全分区字段是动态的,必须至少一个分区字段是指定有值即静态的,且必
--须放在最前面。设置为nonstrict之后所有的分区都可以是动态的了。
set hive.exec.dynamic.partition.mode=nonstrict;
insert overwrite table student_dyna partition (age)  
select id, name, age FROM student;

​ Hive默认是静态分区,我们在插入数据的时候要手动设置分区,如果源数据量很大的时候,那么针对一个分区就要写一个insert,比如说,有很多我们日志数据,我们要按日期作为分区字段,在插入数据的时候手动去添加分区,那样太麻烦。因此,Hive提供了动态分区,动态分区简化了我们插入数据时的繁琐操作。

--设置参数动态分区
--开启动态分区
set hive.exec.dynamic.partition=true;  
--这个属性默认是strict,即限制模式,strict是避免全分区字段是动态的,必须至少一个分区字段是指定有值即静态的,且必
--须放在最前面。设置为nonstrict之后所有的分区都可以是动态的了。
set hive.exec.dynamic.partition.mode=nonstrict;
------------------------------------------------------------------------
--表示每个节点生成动态分区的最大个数,默认是100
set hive.exec.max.dynamic.partitions.pernode=10000;  
--表示一个DML操作可以创建的最大动态分区数,默认是1000
set hive.exec.max.dynamic.partitions=100000;
--表示一个DML操作可以创建的最大文件数,默认是100000
set hive.exec.max.created.files=150000
--将select数据,覆盖到表的动态分区
insert overwrite table table1 partition (ds, hr)  
select key, value, ds, hr FROM table2 WHERE ds is not null;

建议不将表的所有字段做全分区字段,建议指明分区名,然后再插入数据。

动态分区:分区 字段值必须是有限,可控的。

应用场景:已经有表,然后,有需求需要把原来表按照某个字段进行分区统计时,导入时,可以 开启动态分区一次性导入数据。

示例:

开启动态分区导入分区表

设置开启分区

set hive.exec.dynamic.partition=true;

set hive.exec.dynamic.partition.mode=nonstrict;

查询数据动态插入student_dyna表

insert overwrite table student_dyna 
partition(age) 
select
id,
name,
age
from student;

file

4 将数据写入文件系统

file

4.1 将数据写入一个文件

查询表数据导出到某个文件【linux本地/ hdfs】

--语法格式
INSERT OVERWRITE [LOCAL] DIRECTORY directory1
  [ROW FORMAT row_format] [STORED AS file_format] 
  SELECT ... FROM ...

示例:

1)将select的数据写入到hdfs文件中,多层目录会帮你创建

-- 查询ext_task 表中分区为wordcount 的数据,以AVRO 格式写入到hdfs指定目录
insert overwrite directory 'hdfs://ns1/user/panniu/hive26/export_data/d1_avro' STORED AS AVRO
select word, num from ext_task where taskname='wordcount01';

file

img

如果是分区表,导出所有数据时,导出的格式是avro、orc文件格式,如果不加分区导出时,会报错。

但是如果给linux本地导数据,导出的格式是avro、orc文件格式不加分区也不会报错。

insert overwrite directory 'hdfs://ns1/user/panniu/hive26/export_data/d2_avro' STORED AS AVRO

select word, num from ext_task;

如何把分区表中所有数据都导出来avro、orc文件格式

需要通过临时表,作为中间表,先导出到中间表,再从中间表导出avro、orc文件格式的数据。

-- 创建临时中间表s
CREATE TEMPORARY TABLE `task_tmp`(
word string,
num int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
-- 先导出到中间表
insert into table task_tmp
select word, num from ext_task;
-- 再从中间表导出文件
insert overwrite directory 'hdfs://ns1/user/panniu/hive/data456/d2_avro' STORED AS AVRO
select word, num from task_tmp;

file

2)将select的数据写入到本地文件中, 多层目录会自动帮你创建

-- 查询ext_task 表中分区为wordcount 的数据,以text 格式写入到本地目录中
insert overwrite local directory '/home/panniu/hive_test/d1_text'
select word, num from ext_task where taskname='wordcount01';

file

分区表不加分区导出到linux本地不报错。

insert overwrite local directory '/home/panniu/hive_test/d2_avro' STORED AS AVRO
select word, num from ext_task;

file

4.2 将数据写入多个文件

--语法格式
FROM from_statement
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 row_format
select_statement1 where 
[INSERT OVERWRITE [LOCAL] DIRECTORY directory2 row_format
select_statement2 where ] ...
row_format
  : DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS TERMINATED BY char]
        [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
        [NULL DEFINED AS char]

说明:

​ 1)导出到文件系统的数据都序列化成text,非原始类型字段会序列化成json,导出文件以^A分隔 \n结尾的文本数据。

​ 2)INSERT OVERWRITE 到HDFS目录,可以通过MR job实现并行写入。这样在集群上抽取数据不仅速度快,而且还很方便。

​ 3)批量导出多个文件,需要导出文件的类型一致,如果一个是avro,一个是text,报错。

示例:

从一张表中导出两个文件到不同的路径

分区表:需要两个分区一致,在一个分区下,来导出不同条件的数据

from ext_task 
insert overwrite directory 'hdfs://ns1/user/panniu/hive26/output_avro5' STORED AS AVRO 
select 
word,
num 
where taskname='wordcount01' and word='aa'
insert overwrite local directory '/home/panniu/hive_test/output_avro4' STORED AS AVRO 
select 
word,
num 
where taskname='wordcount01' and word='bb';

不是分区表:

在表下,导出不同条件的数据

from student 
insert overwrite directory 'hdfs://ns1/user/panniu/hive/output_avro5' STORED AS AVRO 
select 
id,name
where age=12
insert overwrite local directory '/home/panniu/hive_test/0403/output_avro4' STORED AS AVRO 
select 
id,name
where age=13

file

如果多个输出目录,导出的格式不同,也报错。

报错例子:

from ext_task 
insert overwrite directory 'hdfs://ns1/user/panniu/hive/output_avro5' STORED AS Textfile 
select 
word,
num 
where taskname='wordcount04' 
insert overwrite local directory '/home/panniu/hive_test/0403/output_avro4' STORED AS AVRO 
select 
word,
num 
where taskname='wordcount04';

4.3 hive -e 执行命令 导出

-- 导出数据
hive -e "use c26pan;select word,num from  ext_task where taskname='wordcount01';" > ./output_txt4
-- 后台运行,关心错误信息,输出到某个文件里
nohup hive -e "use c26pan;select word,num from  ext_task where taskname='wordcount01' ;" 1> ./output_txt5 2>./err.log &
-- 后台运行,错误信息不关心,放到无底洞里
nohup hive -e "use c26pan;select word,num from  ext_task where taskname='wordcount01' ;" 1> ./output_txt6 2>/dev/null &

4.4 hive -f 执行SQL文件 导出

[panniu@op 03]$ vim hivesql.sql
use c31pan; select * from ext_task where taskname='wordcount01';
hive -f hivesql.sql > output_data2

file

版权声明:原创作品,允许转载,转载时务必以超链接的形式表明出处和作者信息。否则将追究法律责任。来自海汼部落-阿布都的都,http://hainiubl.com/topics/76053
成为第一个点赞的人吧 :bowtie:
回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter