Hive 数据的导入与导出

数据导入

load 加载数据

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中的文件load到表中

先 rm 原有目录数据,然后上传新数据文件, hdfs 执行mv操作
load data INPATH ‘/user/su/task/wordcount_su’ overwrite into table inner_task2 PARTITION (taskname=‘wordcount’);

执行完后hdfs中原目录数据被移动到表目录下

如果load之前表中没有对应的分区,则自动创建分区目录
load之前

hive> show partitions uis_partition;
OK
dt=20141117
Time taken: 0.078 seconds, Fetched: 1 row(s)

创建一个结构相同的表

hive > create table uis_partition2 (
     >   `aid` string, 
     >   `pkgname` string, 
     >   `uptime` bigint, 
     >   `type` int, 
     >   `country` string, 
     >   `gpcategory` string)
     > PARTITIONED BY ( 
     >   `dt` string);
OK
Time taken: 2.08 seconds

在uis_partition2中创建一个与uis_partition不同的分区,并插入数据

hive > alter table uis_partition2 add partition(dt='20141228') location '2014/12/28';
hive > insert overwrite table uis_partition2 partition(dt='20141228')
     > select 
     > aid,pkgname,uptime,type,country,gpcategory
     > from user_install_status_orc
     > where dt = '20141228';

将uis_partition2 的分区目录导入到uis_partition中,uis_partition多了uis_partition2的分区,而uis_partition2的分区虽然还在,但数据消失了,被移动到了uis_partition

hive > load data inpath 'hdfs://ns1/hive/warehouse/wangchen22_test.db/uis_partition2/2014/12/28' overwrite into table uis_partition partition(dt='20141228');
hive (wangchen22_test)> show partitions uis_partition;
OK
dt=20141117
dt=20141228
Time taken: 0.067 seconds, Fetched: 2 row(s)

hive > show partitions uis_partition2;
OK
dt=20141228
Time taken: 0.062 seconds, Fetched: 1 row(s)
hive > select * from uis_partition2 where dt='20141228' limit 10;
OK
Time taken: 0.117 seconds

将本地文件load到表中

也会自动创建分区表

hive > load data local inpath '/home/wangchen22/file1' overwrite into table uis_partition partition(dt='20141222');

hive > show partitions uis_partition;
OK
dt=20141117
dt=20141222
dt=20141228

filepath不能包含子目录

hive (wangchen22_test)> load data local inpath '/home/wangchen22' overwrite into table uis_partition partition(dt='20141222');
FAILED: SemanticException Line 1:23 Invalid path ''/home/wangchen22'': source contains directory: file:/home/wangchen22/d1

select加载数据

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

overwrite和into只能有一个

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

hive > insert overwrite table uis_partition partition(dt='20141221')
     > select aid,pkgname,uptime,type,country,gpcategory
     > from user_install_status_orc
     > where dt='20141221';
     
自动创建了分区
hive > show partitions uis_partition;
OK
dt=20141117
dt=20141221
dt=20141222
dt=20141228

动态分区

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;

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

创建原始表和分区表

-- 学生表
CREATE TABLE student(
id int,
name string,
age int
)

-- 学生动态分区表
CREATE TABLE student_dyna(
id int,
name string
)
partitioned by (age int)

--导入数据到student后
hive > select * from student;
OK
1       name1   12
2       name2   12
3       name3   13
4       name4   13
5       name5   14
6       name6   14
7       name7   15
8       name8   15

开启自动分区

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;
hive > select * from student_dyna;
OK
1       name1   12
2       name2   12
3       name3   13
4       name4   13
5       name5   14
6       name6   14
7       name7   15
8       name8   15

查看分区目录:

hive > dfs -ls  hdfs://……/student_dyna;
Found 4 items
drwxrwxrwx   - wangchen22 supergroup          0 2020-05-31 11:29 hdfs://……/student_dyna/age=12
drwxrwxrwx   - wangchen22 supergroup          0 2020-05-31 11:29 hdfs://……/student_dyna/age=13
drwxrwxrwx   - wangchen22 supergroup          0 2020-05-31 11:29 hdfs://……/student_dyna/age=14
drwxrwxrwx   - wangchen22 supergroup          0 2020-05-31 11:29 hdfs://……/student_dyna/age=15

数据导出

将数据写入文件系统

将数据写入一个文件

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

导出到hdfs
insert overwrite directory 'hdfs://ns1/user/test/output' 
stored as avro
select * from student;
导出到本地
insert overwrite local directory '/home/user' 
stored as avro
select * from student;

将数据写入多个文件

语法格式
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 student
insert overwrite directory '/user/test/output' stored as textfile
select * 
insert overwrite local directory '/home/user' stored as textfile
select * ;

通过hive -e 命令导出

hive -e “sql” --> 推荐 小规模SQL

hive -f sqlfile 大规模SQL

把sql写入一个文件中

posted @ 2020-05-31 12:42  我不是忘尘  阅读(666)  评论(0编辑  收藏  举报