hive导入数据
Hive 数据导入:HDFS 直接传、LOAD DATA、INSERT,三种方式怎么选?
往 Hive 表里导数据,有三种方式:
| 方式 | 速度 | 复杂度 | 适用场景 |
|---|---|---|---|
| HDFS 直接上传 | 最快 | 最低 | 测试数据、临时导入,不关心元数据 |
LOAD DATA |
快 | 低 | 批量导入原始文件,推荐方式 |
INSERT |
慢 | 中 | 数据需要转换、过滤、聚合后再导入 |
选型一句话:能直接用文件就 LOAD DATA,文件需要处理就用 INSERT,临时随便测测就用 HDFS 直接传。
方式1:HDFS 直接上传——最快,但元数据不同步
这种方式最简单:找到表在 HDFS 上的目录,把文件丢进去。
步骤:
-- 1. 建表
CREATE TABLE dept (
deptno INT,
dname STRING
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
-- 2. 查看表在 HDFS 上的位置
DESC FORMATTED dept;
-- Location: hdfs://localhost:9000/user/hive/warehouse/study_hive.db/dept
3. 直接把数据文件传到表的 HDFS 目录
hdfs dfs -put ./dept.txt /user/hive/warehouse/study_hive.db/dept/
-- 4. 查询验证
SELECT * FROM dept;
-- 数据出来了
特点:
- 最快,没有中间环节
- 不更新元数据(
numFiles、totalSize还是 0) - 不检查数据格式跟表定义是否匹配
什么时候用: 测试环境快速验证,知道文件格式匹配,不在乎元数据统计信息。
风险: 元数据跟实际数据不一致,ANALYZE TABLE 之前统计信息都是错的。
-- 查询表元数据(numFiles、numRows 仍为 0)
select PARAM_KEY, PARAM_VALUE from TABLE_PARAMS where TBL_ID = (select TBL_ID from TBLS where TBL_NAME = 'dept');
+----------------+-------------+
| PARAM_KEY | PARAM_VALUE |
+----------------+-------------+
| numFiles | 0 | -- 实际已有 1 个文件,但元数据未更新
| numRows | 0 | -- 实际已有 2 行数据
| totalSize | 0 |
+----------------+-------------+
方式2:LOAD DATA——官方推荐,自动更新元数据
LOAD DATA 是 Hive 官方的数据导入方式,会自动更新元数据中的文件数和总大小。
语法:
LOAD DATA [LOCAL] INPATH '路径' [OVERWRITE] INTO TABLE 表名;
从本地文件系统导入(LOCAL):
LOAD DATA LOCAL INPATH '/home/hadoop/data/dept.txt' INTO TABLE dept;
- 文件在本地操作系统上
- Hive 把文件复制到 HDFS 表目录(本地文件保留)
从 HDFS 导入(不加 LOCAL):
LOAD DATA INPATH '/tmp/dept.txt' INTO TABLE dept;
- 文件已经在 HDFS 上
- Hive 把文件移动到 HDFS 表目录(原路径的文件会被删掉)
特点:
- 自动更新元数据(
numFiles、totalSize) - 只是移动/复制文件,不解析数据内容
- 支持覆盖(
OVERWRITE)和追加(默认)
什么时候用: 批量导入原始数据文件,这是最常用的方式。
一个坑: LOAD DATA 不更新行数(numRows),行数要用 ANALYZE TABLE 手动统计。
-- 统计行数
ANALYZE TABLE dept COMPUTE STATISTICS;
方式3:INSERT——数据需要处理时用
如果数据不是直接能用的原始文件,需要过滤、转换、聚合后再导入,用 INSERT。
-- 直接从值插入
INSERT INTO TABLE dept VALUES (201, '人事'), (202, '公关');
-- 从查询结果插入
INSERT OVERWRITE TABLE dept
SELECT deptno, dname FROM raw_dept WHERE deptno > 100;
-- 从另一张表查过来
INSERT INTO TABLE dept
SELECT * FROM dept_staging;
INSERT INTO vs INSERT OVERWRITE:
| INSERT INTO | INSERT OVERWRITE | |
|---|---|---|
| 行为 | 追加数据 | 覆盖已有数据 |
| 原数据 | 保留 | 被替换 |
特点:
- 可以处理数据(过滤、转换、聚合)
- 会触发 MapReduce/Tez/Spark 任务,有额外开销
- 小数据量导入比 LOAD DATA 慢
什么时候用: 数据需要清洗、格式转换、从多张表关联后导入。
三种方式对比
| 对比项 | HDFS 直接上传 | LOAD DATA | INSERT |
|---|---|---|---|
| 操作复杂度 | 最低 | 低 | 中 |
| 速度 | 最快 | 快 | 慢(触发了计算任务) |
| 元数据更新 | 不更新 | 更新文件数/大小 | 更新文件数/大小 |
| 数据能否处理 | 不能 | 不能 | 能(过滤、转换、聚合) |
| 适用场景 | 测试、临时导入 | 批量导入原始文件 | 数据需要处理后导入 |
元数据不同步的问题
HDFS 直接上传最大的问题是元数据不同步。执行 SHOW TABLE EXTENDED 或者看统计信息时,数据不准确。
现象:
-- 明明表里有数据,但 numFiles 和 numRows 还是 0
SELECT param_key, param_value FROM TABLE_PARAMS
WHERE tbl_id = (SELECT tbl_id FROM TBLS WHERE tbl_name='dept');
-- numFiles: 0 ← 实际已经有文件了
-- numRows: 0 ← 实际已经有数据了
解决方式:
- 用
LOAD DATA替代 HDFS 直接上传 - 如果已经用 HDFS 上传了,手动执行
ANALYZE TABLE同步元数据
ANALYZE TABLE dept COMPUTE STATISTICS;