Hive 的数据插入与传统的数据库(如 MySQL)有显著不同,因为它底层是基于 Hadoop 的 HDFS 文件系统。其核心思想是:将插入语句转换为一个或多个 MapReduce 或 Spark 作业,最终在 HDFS 上生成数据文件。
Hive 中数据插入主要分为以下几种方式,其流程各有特点:
- 使用
LOAD DATA语句(数据迁移) - 使用
INSERT语句(计算和插入) - 使用
INSERT ... VALUES语句(少量数据插入)
1. 使用 LOAD DATA 语句
这种方式主要用于将已存在的文件快速加载到 Hive 表中,它本质上是一个文件移动或复制的操作,不涉及数据转换计算。
语法:
LOAD DATA [LOCAL] INPATH 'file_path' [OVERWRITE] INTO TABLE table_name [PARTITION (partcol1=val1, partcol2=val2 ...)];
流程详解:
-
路径解析:Hive 首先解析
file_path。- 如果指定了
LOCAL关键字,表示路径是本地文件系统(如 Linux 系统)的路径。Hive 会将文件复制到 HDFS 上的表目录中。 - 如果没有指定
LOCAL,表示路径是 HDFS 上的路径。Hive 会将文件移动到表目录中。
- 如果指定了
-
目标确定:Hive 确定目标表的位置,即其在 HDFS 上的目录(例如
/user/hive/warehouse/my_db.db/my_table/)。如果是分区表,还会确定具体分区的目录(例如/user/hive/warehouse/my_db.db/my_table/country=CN/)。 -
文件操作:
- 移动(HDFS路径):HDFS 的
mv命令非常高效,因为它只更改元数据(指针),而不实际移动数据块。这是最快的数据加载方式。 - 复制(本地路径):需要将数据从本地磁盘通过网络传输到 HDFS。
- 移动(HDFS路径):HDFS 的
-
元数据更新:Hive 的 Metastore 会更新这张表的元数据信息,记录新增了哪些数据文件。但请注意,Hive 不会立即去解析这些文件的内容来更新统计信息(如行数),可能需要执行
ANALYZE TABLE命令来更新。
特点:
- 速度快:因为是文件级别的操作。
- 无转换:数据不会经过任何处理,原样加载。
- 常用于:ETL 过程前期,将原始数据文件加载到 ODS 层(原始数据层)。
2. 使用 INSERT 语句(最常用)
这种方式用于将查询结果插入到另一张表中。它会启动一个完整的 MapReduce/Spark 作业来处理数据并写入目标位置。这是 Hive 中最核心的数据插入方式。
语法:
FROM source_table
INSERT [OVERWRITE | INTO] TABLE target_table [PARTITION (partcol1=val1, partcol2=val2 ...)]
SELECT select_expression, ...
[WHERE where_condition];
流程详解:
-
语法解析和编译:Hive 首先对 SQL 语句进行解析、编译和优化,生成一个查询计划(Query Plan)。
-
执行引擎转换:Hive 将查询计划转换为一个 MapReduce 或 Tez 或 Spark 作业。
- Map 阶段:读取源表的数据,进行过滤、投影(选择字段)、转换等操作。
- Reduce 阶段(可选):如果需要排序、聚合或分发数据到不同的分区,就会触发 Reduce 阶段。
-
数据写入:
- 执行引擎(如 MapTask 或 ReduceTask)处理完数据后,会开始写入数据。
- 文件格式:数据会以目标表定义的存储格式(如 TextFile, ORC, Parquet)被写入。
- 目录结构:
- 如果是非分区表,数据直接写入表的根目录。
- 如果是分区表,执行引擎会根据
PARTITION子句中指定的值,将数据写入对应的分区目录(例如.../table/country=CN/)。如果目录不存在,Hive 会自动创建它。
OVERWRITEvsINTO:OVERWRITE:会先删除目标表(或指定分区)的现有数据,然后再写入新数据。INTO:以追加的方式将新数据插入到目标表(或指定分区)中,原有数据保留。
-
生成文件:Hive 通常会在 HDFS 上生成多个文件(因为多个 Reduce Task 并行写入),文件名为类似
000000_0的形式。 -
元数据更新:与
LOAD DATA类似,Hive Metastore 会更新元数据,记录新文件的信息。
特点:
- 功能强大:可以在插入过程中进行复杂的转换、过滤和聚合。
- 速度较慢:因为涉及分布式计算。
- 常用于:数据仓库的各个层级之间的数据流转和加工(如从 ODS 层到 DWD 层)。
3. 使用 INSERT ... VALUES 语句
这种方式类似于传统 SQL,用于插入少量数据,不推荐用于大批量数据插入。
语法:
INSERT INTO TABLE table_name [PARTITION (partcol1=val1, ...)]
VALUES (value1, value2, ...), (value1, value2, ...), ...;
流程详解:
- 本地作业:对于小量数据,Hive 可能会启动一个本地模式(Local Mode)的 MapReduce 作业,以避免与集群交互的开销。
- 写入文件:即使只插入一行数据,Hive 也会在 HDFS 上创建一个新文件(或追加到现有文件)。如果你频繁执行单条
INSERT ... VALUES,会导致表中存在大量小文件,这是 Hive 的一个大忌,会严重拖慢后续查询性能。 - 元数据更新:更新 Metastore。
特点:
- 方便:语法简单直观。
- 性能极差:每条语句都可能产生一个小的 MapReduce 作业和一个小的 HDFS 文件。
- 适用场景:仅用于测试或初始化极少量数据。生产环境应避免使用。
总结与对比
| 特性 | LOAD DATA | INSERT ... SELECT | INSERT ... VALUES |
|---|---|---|---|
| 本质 | 文件移动/复制 | 分布式计算作业 | 小型计算作业 |
| 速度 | 非常快 | 慢(取决于计算复杂度) | 非常慢(相对量级) |
| 数据转换 | 无 | 有,可通过 SELECT 实现 | 无 |
| 产生小文件 | 不会(除非加载很多小文件) | 可能(取决于 Reduce 数量) | 极易产生 |
| 主要用途 | 初始数据加载 | ETL 数据处理管道 | 测试、初始化少量数据 |
最佳实践建议:
- 大数据量加载首选
LOAD DATA(如果数据已准备好)或INSERT ... SELECT(如果需要转换)。 - 绝对避免在生产环境中使用循环语句频繁调用
INSERT ... VALUES。 - 使用
INSERT ... SELECT时,注意调整 Reduce 任务数量,以避免产生过多小文件。可以通过hive.exec.reducers.bytes.per.reducer等参数来控制。

552

被折叠的 条评论
为什么被折叠?



