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;
-- 数据出来了

特点:

  • 最快,没有中间环节
  • 不更新元数据(numFilestotalSize 还是 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 表目录(原路径的文件会被删掉)

特点:

  • 自动更新元数据(numFilestotalSize
  • 只是移动/复制文件,不解析数据内容
  • 支持覆盖(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;