Hive创建外部表读取CSV文件详解

9 次阅读

Hive作为大数据分析领域常用的数据仓库工具,能够通过SQL方式对存储在分布式文件系统中的数据进行查询和分析。其中,CSV文件由于格式简单、兼容性强,在数据交换、日志导入、业务数据归档等场景中被广泛使用。通过Hive创建外部表读取CSV文件,可以避免数据重复加载,提高数据管理效率,是实际数据开发中的常见操作。

Hive外部表与CSV文件概述

Hive中的表主要分为内部表(Managed Table)和外部表(External Table)两种类型。

内部表由Hive负责管理数据和元数据,当删除表时,Hive会同时删除对应的数据文件。而外部表只管理数据的元信息,数据文件仍然由用户或其他系统维护,删除外部表不会影响原始数据。

对于CSV文件来说,通常推荐使用外部表进行读取,原因包括:

  • CSV文件可能由业务系统、日志系统或ETL任务生成,不适合由Hive直接管理。

  • 多个计算引擎可能同时访问同一份CSV数据。

  • 删除Hive表时不会误删源文件,数据安全性更高。

  • 避免数据复制,节省HDFS存储空间。

因此,在数据仓库开发中,Hive外部表读取CSV是一种更加灵活可靠的方案。

Hive读取CSV文件的基本流程

使用Hive外部表读取CSV文件通常包含以下几个步骤:

  1. 将CSV文件上传到HDFS指定目录。

  2. 创建Hive外部表。

  3. 指定字段分隔符。

  4. 设置表对应的数据路径。

  5. 执行查询验证数据读取效果。

假设HDFS中存在如下CSV文件:

/data/user/user_info.csv

文件内容如下:

1001,Tom,25,Beijing
1002,Jack,30,Shanghai
1003,Lily,28,Shenzhen

对应的数据字段如下:

字段含义
id用户编号
name用户名
age年龄
city城市

创建Hive外部表读取CSV文件

最基础的CSV外部表创建语句如下:

SQL
CREATE EXTERNAL TABLE user_info (
    id INT,
    name STRING,
    age INT,
    city STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LOCATION '/data/user/';

执行成功后,Hive会读取/data/user/目录下的CSV文件。

其中关键参数说明:

EXTERNAL关键字

SQL
CREATE EXTERNAL TABLE

表示创建外部表。

如果不添加EXTERNAL,Hive默认创建内部表,删除表时可能导致数据文件被删除。

ROW FORMAT DELIMITED

表示使用文本格式解析数据。

CSV文件本质上属于结构化文本文件,需要告诉Hive如何拆分字段。

FIELDS TERMINATED BY ','

表示字段之间使用英文逗号分隔。

例如:

1001,Tom,25,Beijing

Hive会解析为:

id=1001
name=Tom
age=25
city=Beijing

LOCATION

指定CSV文件所在的HDFS目录:

SQL
LOCATION '/data/user/';

Hive不会移动文件,而是直接读取该目录中的数据。

CSV文件包含表头时的处理方法

很多业务CSV文件第一行包含字段名称,例如:

id,name,age,city
1001,Tom,25,Beijing
1002,Jack,30,Shanghai

如果直接读取,Hive会把第一行当成数据:

id=name
name=name
age=age
city=city

导致类型转换异常。

可以使用Hive参数跳过表头:

SQL
CREATE EXTERNAL TABLE user_info (
    id INT,
    name STRING,
    age INT,
    city STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LOCATION '/data/user/'
TBLPROPERTIES (
    "skip.header.line.count"="1"
);

其中:

SQL
skip.header.line.count

表示跳过CSV文件前面的指定行数。

通常CSV只有一行标题,因此设置为:

SQL
"skip.header.line.count"="1"

即可。

处理CSV字段中包含逗号的问题

标准CSV文件可能存在字段内容包含逗号的情况,例如:

1001,"Tom,Smith",25,Beijing

简单使用:

SQL
FIELDS TERMINATED BY ','

会导致字段拆分错误。

这种情况下,需要使用Hive支持的CSV SerDe。

常见方式如下:

SQL
CREATE EXTERNAL TABLE user_info (
    id INT,
    name STRING,
    age INT,
    city STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
    "separatorChar"=",",
    "quoteChar"="""
)
LOCATION '/data/user/';

OpenCSVSerde能够识别:

  • 双引号包裹字段

  • 字段内部逗号

  • 特殊字符转义

更适合生产环境中的复杂CSV数据。

Hive外部表读取本地CSV文件

如果CSV文件位于Linux本地目录,需要先上传到HDFS:

Bash
hdfs dfs -put user_info.csv /data/user/

查看文件:

Bash
hdfs dfs -ls /data/user/

确认上传成功后,再创建Hive外部表。

Hive通常不直接读取本地文件系统中的CSV,因为分布式环境下每个节点的本地路径可能不同。

查询CSV外部表数据

创建完成后,可以执行:

SQL
SELECT * FROM user_info;

查看数据:

1001 Tom 25 Beijing
1002 Jack 30 Shanghai
1003 Lily 28 Shenzhen

也可以进行条件查询:

SQL
SELECT name,city
FROM user_info
WHERE age > 25;

结果:

Jack Shanghai
Lily Shenzhen

这说明Hive已经成功解析CSV文件。

常见问题与解决方案

1. 查询结果字段全部为空

可能原因:

  • CSV分隔符设置错误。

  • 文件编码异常。

  • 字段格式不匹配。

检查CSV:

Bash
hdfs dfs -cat /data/user/user_info.csv

确认实际分隔符。

例如文件使用制表符:

1001    Tom    25

则需要:

SQL
FIELDS TERMINATED BY '	'

2. 中文乱码问题

CSV文件如果使用GBK编码,而Hive默认按照UTF-8读取,可能出现乱码。

解决方式:

将文件转换为UTF-8:

Bash
iconv -f GBK -t UTF-8 user_info.csv > user_utf8.csv

然后重新上传HDFS。


3. 删除Hive表导致CSV文件消失

如果执行:

SQL
DROP TABLE user_info;

发现数据文件被删除,说明创建的是内部表。

查看表类型:

SQL
DESC FORMATTED user_info;

如果:

Table Type: MANAGED_TABLE

表示内部表。

外部表应该显示:

Table Type: EXTERNAL_TABLE

4. CSV新增文件后是否需要重新建表

外部表不需要重新创建。

例如:

/data/user/
    user1.csv
    user2.csv
    user3.csv

Hive会自动读取目录中的新增文件:

SQL
SELECT COUNT(*) FROM user_info;

即可看到最新数据。

Hive读取CSV的性能优化建议

CSV属于文本格式,虽然使用方便,但查询效率相对较低。在生产环境中,通常采用以下优化方式:

转换为ORC或Parquet格式

CSV适合数据导入,不适合作为长期查询存储。

可以通过Hive转换:

SQL
CREATE TABLE user_info_orc
STORED AS ORC
AS
SELECT * FROM user_info;

ORC格式具有:

  • 列式存储

  • 压缩率高

  • 查询速度快

  • 支持谓词下推

适合作为数据仓库存储格式。

合理规划分区

对于大型CSV数据,可以创建分区表:

SQL
CREATE EXTERNAL TABLE user_log (
    id INT,
    message STRING
)
PARTITIONED BY (
    dt STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LOCATION '/data/log/';

按照日期、业务类型等字段分区,可以减少扫描数据量。

避免小文件过多

大量CSV小文件会导致:

  • NameNode压力增加。

  • Hive任务启动时间变长。

  • Map任务数量增加。

可以通过合并文件:

Bash
hdfs dfs -getmerge

或者使用Spark、MapReduce进行文件合并。

Hive外部表读取CSV的应用场景

Hive创建外部表读取CSV广泛应用于以下场景:

数据仓库初始化

业务系统导出的CSV文件可以快速接入Hive,作为ODS层数据来源。

日志分析

服务器日志、访问记录、监控数据经CSV格式落地后,可以通过Hive进行统计分析。

数据交换

不同系统之间通过CSV传输数据时,Hive可以直接读取,无需额外转换。

数据迁移

从传统数据库导出的CSV文件,可以快速导入大数据平台进行分析。

总结

Hive创建外部表读取CSV文件是一种简单、高效的数据接入方式。通过CREATE EXTERNAL TABLE、ROW FORMAT DELIMITED以及FIELDS TERMINATED BY等配置,可以快速实现CSV数据查询。

在实际项目中,需要根据CSV文件特点选择合适方案:

  • 简单CSV文件使用字段分隔符解析即可。

  • 包含引号、逗号等复杂内容时建议使用OpenCSVSerde。

  • 大规模分析场景建议将CSV转换为ORC或Parquet格式。

  • 生产环境优先使用外部表,避免误删源数据。

掌握Hive外部表读取CSV的方法,可以帮助数据开发人员更加灵活地完成数据接入、清洗和分析任务。