Hive:DML 数据操作——Load、Insert、Export、Import 四种数据进出方式
Hive数据进出有四种方式:LOAD DATA(本地复制、HDFS剪切)用于批量加载文件;INSERT SELECT实现表间结果集迁移,支持追加或覆盖;INSERT VALUES可手动插入单行,但生产慎用;INSERT DIRECTORY将查询结果导出至本地或HDFS文件系统;EXPORT/IMPORT则支持整表连同元数据的跨集群迁移。其中,LOAD最高效,INSERT适用于加工逻辑,EXPORT/IMPORT适合表级迁移。核心原则:能用LOAD就不用INSERT,数据操作以文件和批量为主。
目录
- 一、先想清楚:为什么 Hive 灌数据和 MySQL 不一样
- 二、方式一:LOAD DATA 加载文件(最常用)
- 三、方式二:INSERT 把查询结果插入表
- 四、方式三:INSERT VALUES 直接插值
- 五、方式四:查询结果导出到文件系统
- 六、EXPORT / IMPORT:带元数据的导入导出
- 七、四种方式对比总结
一、先想清楚:为什么 Hive 灌数据和 MySQL 不一样
在 MySQL 里你习惯了随时insert into ... values(...)单条插、update单条改。到 Hive 里请先换个思维:
Hive 是面向批量分析的数仓工具,不是事务数据库。数据进出的主角是"文件"和"批量结果集",而不是"单行记录"。
所以 Hive 的 DML 围绕四个问题展开:
- 本地/集群的文件怎么整批装进表?→ LOAD DATA
- 一张表的查询结果怎么存进另一张表?→ INSERT SELECT
- 表里的数据怎么导出成文件?→ INSERT DIRECTORY / EXPORT
- 整张表连结构带数据怎么搬家?→ EXPORT / IMPORT
下面逐一实操。统一使用 students 表:
createtableifnotexistsbigdata.students1(id stringcomment'学号',name stringcomment'姓名',ageintcomment'年龄',sex stringcomment'性别',clazz stringcomment'班级')rowformat delimitedfieldsterminatedby',';二、方式一:LOAD DATA 加载文件(最常用)
2.1 语法
LOADDATA[LOCAL]INPATH'filepath'[OVERWRITE]INTOTABLEtablename[PARTITION(partcol1=val1,...)]三个可选零件,每个都是考点:
| 零件 | 不写 / 写了 的区别 |
|---|---|
| LOCAL | 写:从 Linux 本地路径加载;不写:从 HDFS 路径加载 |
| OVERWRITE | 写:清空表里原有数据再装;不写:追加到表尾 |
| PARTITION | 分区表指定装到哪个分区(第 4 篇展开) |
2.2 加载本地文件:复制
loaddatalocalinpath'/root/sh_code/student.csv'overwriteintotablestudents1;查询验证:
select*fromstudents1limit3;输出:
OK id name age sex clazz 1500100001 施笑槐 22 男 理科一班 1500100002 吕梓杨 24 男 理科二班 1500100003 张三 21 女 理科一班 Time taken: 2.104 seconds, Fetched: 3 row(s)本质:把本地文件复制一份到表的 HDFS 目录下。本地原文件还在。
2.3 加载 HDFS 文件:剪切!
先准备一张同结构的空表,把文件先传到 HDFS:
hdfs dfs-putstudent.csv /student.csvcreatetableifnotexistsbigdata.students2likestudents1;loaddatainpath'/student.csv'overwriteintotablestudents2;再查一下 HDFS 根目录:
hdfs dfs-ls/Found 3 items -rw-r--r-- ... /students5 (其他文件) drwxr-xr-x ... /data # /student.csv 不见了!它被"移动"进了 students2 的表目录核心区别(面试可考):
| 来源 | 行为 | 原文件 |
|---|---|---|
load data local | 复制到表目录 | 还在 |
load data (hdfs) | 移动到表目录 | 消失(相当于 mv) |
口诀:本地复制,HDFS 剪切。道理很简单:数据都已经在 HDFS 上了,再复制一份纯属浪费存储,挪个目录就完事。
2.4 OVERWRITE 追加实验
不加 OVERWRITE 就是追加。连续执行两次加载(去掉 overwrite):
loaddatalocalinpath'/root/sh_code/student.csv'intotablestudents1;loaddatalocalinpath'/root/sh_code/student.csv'intotablestudents1;selectcount(1)fromstudents1;OK _c0 1000 (假设原文件1000行,现在翻倍了)生产建议:写脚本重复执行时,先想清楚要"追加"还是"覆盖",用错 OVERWRITE 会把辛苦算好的数据清掉,用错追加会数据翻倍。
三、方式二:INSERT 把查询结果插入表
3.1 INSERT INTO vs INSERT OVERWRITE
-- into:追加写入insertintotablestudents5select*fromstudents1;-- overwrite:清空目标表再写入insertOVERWRITEtablestudents5select*fromstudents1;典型场景:宽表加工。比如从学生明细表算出一张"每班人数汇总表":
insertoverwritetableclazz_countselectclazz,count(1)asnumfromstudents1groupbyclazz;这个"查询结果落成一张新表"的模式,就是数仓分层(ODS → DWD → DWS)最基础的动作。
3.2 性能提醒
insert ... select底层是一个 MapReduce 任务,比 load 慢得多。原则:能 load 不 insert;表到表的加工才用 insert。
四、方式三:INSERT VALUES 直接插值
insertintotablestudents5VALUES('100001','张三',25,'1','文科一班');能跑,但生产上基本不用:
- 插一条数据也要起一个 MR 任务,秒级变分钟级
- 数仓的数据来源是批量文件或上游表,不存在"手工逐行插"
了解即可,别养成习惯。
五、方式四:查询结果导出到文件系统
5.1 单路导出
INSERTOVERWRITE[LOCAL]DIRECTORY directory1[ROWFORMAT row_format][STOREDASfile_format]SELECT...FROM...;案例:把表数据导出到 Linux 本地目录,逗号分隔:
insertoverwritelocaldirectory'/root/students5'rowformat delimitedfieldsterminatedby','select*fromstudents5;查看结果:
cat/root/students5/000000_0|head-31500100001,施笑槐,22,男,理科一班 1500100002,吕梓杨,24,男,理科二班 1500100003,张三,21,女,理科一班几个细节:
- 不写
LOCAL就是导到 HDFS 目录 - 结果文件名固定形如
000000_0,有几个 Reduce 就有几个文件 row format ... terminated by ','决定导出文件的分隔符,不写默认是控制符\001,打开会全是乱码
5.2 多路导出(Multiple Inserts)
一次查询结果可以同时导到多个地方,语法是从FROM开头:
FROMstudents5INSERTOVERWRITELOCALDIRECTORY'/root/out_male'SELECT*WHEREsex='男'INSERTOVERWRITELOCALDIRECTORY'/root/out_female'SELECT*WHEREsex='女';一次扫描、多份输出,省了重复读表的开销。
六、EXPORT / IMPORT:带元数据的导入导出
前面四种方式只搬"数据",EXPORT/IMPORT 连元数据(表结构等)一起打包,常用于集群间整表迁移。
6.1 导出
EXPORTTABLEstudents5TO'/students5';6.2 导入
先把目标表清空(模拟"换个集群的空表"):
truncatetablestudents1;importtablestudents1from'/students5';验证:
selectcount(1)fromstudents1;OK _c0 1000数据回来了。注意 EXPORT/IMPORT 走的是 HDFS 路径,迁移跨集群时通常配合distcp把导出目录拷到目标集群再 IMPORT。
七、四种方式对比总结
| 方式 | 方向 | 数据粒度 | 是否动元数据 | 典型场景 |
|---|---|---|---|---|
| LOAD DATA(local) | 文件 → 表 | 整个文件 | 否 | 灌原始数据,最快 |
| LOAD DATA(hdfs) | 文件 → 表 | 整个文件 | 否 | HDFS 上已有文件挂到表(剪切) |
| INSERT SELECT | 表 → 表 | 结果集 | 否 | 数仓分层加工 |
| INSERT VALUES | 手工 → 表 | 单行 | 否 | 测试玩玩,生产不用 |
| INSERT DIRECTORY | 表 → 文件 | 结果集 | 否 | 导出分析结果 |
| EXPORT / IMPORT | 表 ↔ HDFS 目录 | 整表 | 是(连结构) | 跨集群整表迁移 |
一句话收尾:日常数据处理 90% 只用两个动作——load灌数、insert ... select加工;剩下四个了解即可,面试和救急时能想起来就行。