Hive 数据导出到 CSV 文件的完整指南

方法一:使用 Hive 命令行工具

基本导出

1
hive -e 'select * from your_table' | sed 's/[\t]/,/g' > /home/yourfile.csv

包含表头

1
hive -e 'set hive.cli.print.header=true; select * from your_table' | sed 's/[\t]/,/g' > /home/yourfile.csv

方法二:使用 INSERT OVERWRITE 语句

Hive 11+ 版本

1
2
3
4
5
6
7
8
-- 导出到本地目录
INSERT OVERWRITE LOCAL DIRECTORY '/home/carter/staging'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
SELECT * FROM hugetable;

-- 合并生成的文件
cat /home/carter/staging/* > /home/carter/table.csv

导出到 HDFS

1
2
3
4
5
6
7
8
-- 导出到 HDFS 目录
INSERT OVERWRITE DIRECTORY '/user/hive/export'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
SELECT * FROM hugetable;

-- 从 HDFS 下载到本地
hadoop fs -getmerge /user/hive/export /home/carter/table.csv

方法三:使用 Beeline

1
2
3
4
5
6
7
8
beeline -u "jdbc:hive2://${ip}:10000" \
-n username \
-p password \
--silent=true \
--outputformat=csv2 \
--incremental=true \
-e 'SELECT * FROM your_table' \
> /data/export/table.csv

方法四:使用 Hive Server2 和 JDBC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import java.sql.*;
import java.io.*;

public class HiveExportCSV {
public static void main(String[] args) throws Exception {
// 连接 Hive
Class.forName("org.apache.hive.jdbc.HiveDriver");
Connection conn = DriverManager.getConnection("jdbc:hive2://localhost:10000/default", "username", "password");

// 执行查询
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM your_table");

// 获取元数据
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();

// 创建 CSV 文件
FileWriter writer = new FileWriter("/home/yourfile.csv");

// 写入表头
for (int i = 1; i <= columnCount; i++) {
writer.append(rsmd.getColumnName(i));
if (i < columnCount) writer.append(",");
}
writer.append("\n");

// 写入数据
while (rs.next()) {
for (int i = 1; i <= columnCount; i++) {
writer.append(rs.getString(i));
if (i < columnCount) writer.append(",");
}
writer.append("\n");
}

// 关闭资源
writer.close();
rs.close();
stmt.close();
conn.close();
}
}

处理复杂数据类型

导出包含数组、映射和结构体的表

1
2
3
4
5
6
7
8
9
10
11
12
-- 处理数组
INSERT OVERWRITE LOCAL DIRECTORY '/home/export'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
COLLECTION ITEMS TERMINATED BY '|'
SELECT
id,
concat_ws('|', array_col),
map_keys(map_col)[0],
struct_col.field1,
struct_col.field2
FROM complex_table;

性能优化

1. 分区裁剪

1
2
3
4
5
6
-- 只导出特定分区的数据
INSERT OVERWRITE LOCAL DIRECTORY '/home/export'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
SELECT * FROM your_table
WHERE partition_col = '2021-05-23';

2. 使用并行执行

1
hive -e 'set hive.exec.parallel=true; set hive.exec.parallel.thread.number=8; select * from your_table' | sed 's/[\t]/,/g' > /home/yourfile.csv

3. 限制数据量

1
2
3
4
5
-- 导出前 1000 行
INSERT OVERWRITE LOCAL DIRECTORY '/home/export'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
SELECT * FROM your_table LIMIT 1000;

4. 使用 Tez 执行引擎

1
hive -e 'set hive.execution.engine=tez; select * from your_table' | sed 's/[\t]/,/g' > /home/yourfile.csv

处理特殊字符

处理包含逗号、引号的数据

1
2
3
4
5
6
7
8
9
-- 使用引号包裹字段
INSERT OVERWRITE LOCAL DIRECTORY '/home/export'
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
"separatorChar" = ",",
"quoteChar" = "\"",
"escapeChar" = "\\"
)
SELECT * FROM your_table;

常见问题及解决方案

1. 导出文件过大

解决方案

  • 使用分区导出
  • 增加并行度
  • 使用 HDFS 导出然后合并

2. 导出速度慢

解决方案

  • 使用 Tez 执行引擎
  • 增加内存分配:set hive.tez.container.size=4096;
  • 优化查询计划

3. 数据格式错误

解决方案

  • 确保正确设置分隔符
  • 处理特殊字符
  • 验证数据类型

自动化导出脚本

以下是一个完整的导出脚本示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash

# 配置参数
HIVE_SERVER="localhost"
HIVE_PORT="10000"
USERNAME="hive"
PASSWORD="hive"
DATABASE="default"
TABLE="your_table"
OUTPUT_DIR="/home/export"
OUTPUT_FILE="${OUTPUT_DIR}/${TABLE}_$(date +%Y%m%d).csv"

# 创建输出目录
mkdir -p ${OUTPUT_DIR}

# 执行导出
echo "开始导出 ${TABLE} 数据..."
beeline -u "jdbc:hive2://${HIVE_SERVER}:${HIVE_PORT}/${DATABASE}" \
-n ${USERNAME} \
-p ${PASSWORD} \
--silent=true \
--outputformat=csv2 \
-e "SELECT * FROM ${TABLE}" \
> ${OUTPUT_FILE}

if [ $? -eq 0 ]; then
echo "导出成功!文件保存至:${OUTPUT_FILE}"
echo "文件大小:$(du -h ${OUTPUT_FILE} | cut -f1)"
else
echo "导出失败!"
exit 1
fi

参考资料

  1. Apache Hive 官方文档
  2. Hive SerDe 文档
  3. OpenCSVSerde 文档
  4. https://www.it-swarm.cn/zh/csv/%E5%A6%82%E4%BD%95%E5%B0%86hive%E8%A1%A8%E5%AF%BC%E5%87%BA%E5%88%B0csv%E6%96%87%E4%BB%B6%EF%BC%9F/1073244602/
  5. https://www.docs4dev.com/docs/zh/apache-hive/3.1.1/reference/LanguageManual_WindowingAndAnalytics.html