hive导出数据

Hive 数据导出:INSERT OVERWRITE、HDFS 下载、Shell 重定向、EXPORT,四种方式怎么选?

往 Hive 外面导数据,有四种方式:

方式 数据去哪 格式可控 含元数据 适用场景
INSERT OVERWRITE LOCAL 本地文件系统 可指定分隔符 不含 导出给 Excel/MySQL 等工具用
INSERT OVERWRITE HDFS HDFS 目录 可指定分隔符 不含 集群内数据共享
Hive Shell 重定向(-e / -f) 本地文件 默认制表符 不含 脚本化导出、定时任务
EXPORT HDFS 目录 固定格式 表迁移、备份恢复

方式1:INSERT OVERWRITE LOCAL——导出到本地,格式可控

这是最常用的导出方式,把查询结果导出到客户端机器的本地目录,可以指定分隔符。

语法:

INSERT OVERWRITE LOCAL DIRECTORY '/本地路径'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'   -- 指定分隔符
SELECT * FROM dept;

实操:

-- 导出到 /tmp/hive_export,用逗号分隔(CSV 格式)
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/hive_export'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
SELECT deptno, dname FROM dept;

验证:

ls /tmp/hive_export/
# 000000_0  ← Hive 生成的文件

cat /tmp/hive_export/000000_0
# 1,财务
# 2,IT

特点:

  • 可以指定分隔符(CSV、TSV、自定义)
  • 导出到运行 Hive 的那台机器上
  • 会触发 MapReduce/Tez 任务(小数据也慢)

什么时候用: 导出结果给 Excel、报表工具、其他系统用。

方式2:INSERT OVERWRITE HDFS——导出到 HDFS,集群内共享

跟方式1一样,只是导出到 HDFS 而不是本地。

语法:

INSERT OVERWRITE DIRECTORY '/hdfs路径'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
SELECT * FROM dept;

特点:

  • 数据留在 HDFS 上,其他集群内工具可以直接读
  • 同样可以指定分隔符
  • 同样触发计算任务

什么时候用: 导出结果给 Spark、Flink 等其他引擎读,或者做数据交换。

方式3:Hive Shell 重定向——脚本化导出,适合定时任务

不进入 Hive 交互模式,在命令行直接执行 SQL 并把结果重定向到文件。

单条 SQL(-e):

hive -e "SELECT deptno, dname FROM study_hive.dept;" > /tmp/dept.txt

多条 SQL 用脚本(-f):

# 写一个 SQL 文件
echo "SELECT deptno, dname FROM study_hive.dept WHERE deptno > 100;" > query.sql

# 执行并导出
hive -f query.sql > /tmp/dept_filtered.txt

去掉日志干扰(-S 静默模式):

hive -S -e "SELECT * FROM dept;" > /tmp/dept_clean.txt

特点:

  • 适合定时任务(crontab + hive -e)
  • 默认分隔符是制表符(\t
  • 结果文件就是纯文本,没有表头

什么时候用: 每天定时导出报表、数据同步脚本。

方式4:EXPORT——带元数据导出,用于备份和迁移

EXPORT 不光导数据,还导表结构——相当于把整张表”打包”。

导出:

EXPORT TABLE study_hive.dept TO '/user/hive/export/dept';

导出后在 HDFS 上看到两个东西:

hdfs dfs -ls /user/hive/export/dept/
# _metadata  ← 表结构元数据
# data       ← 实际数据

导入(IMPORT):

IMPORT TABLE study_hive.dept_restore
FROM '/user/hive/export/dept';

特点:

  • 导出包含元数据,导入时自动建表
  • 不能指定分隔符(固定格式)
  • 只支持整表导出(不能 WHERE 过滤)

什么时候用: 表级备份、集群间迁移、跨环境同步。

一个关键坑:列式存储导出来是二进制

如果表用的是 Parquet、ORC 这种列式存储,INSERT OVERWRITE 导出的文件是二进制格式——cat 出来是乱码。

-- 表是 ORC 格式
CREATE TABLE dept_orc STORED AS ORC AS SELECT * FROM dept;

-- 直接导出
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/dept_export'
SELECT * FROM dept_orc;

cat /tmp/dept_export/000000_0
# 乱码 ── 因为 ORC 是二进制格式

解决方案:

导出时转换成文本格式:

INSERT OVERWRITE LOCAL DIRECTORY '/tmp/dept_export'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
SELECT * FROM dept_orc;   -- 读 ORC,写文本,自动转了

或者先建一张文本格式的临时表,导进去再导出。