外部表(EXTERNAL_TABLE)Hive 借用数据,删表不删数据

外部表(EXTERNAL_TABLE)的核心价值在于数据独立于Hive存在,允许Hive"借用"HDFS上已有的数据,删除表时不会影响原始数据。


主要使用场景包括:

1)多引擎共享数据(Hive/Spark/Presto共用);

2)外部系统(如Flume)实时写入的数据;

3)已有特定目录结构的数据;

4)需要保留原始数据的ETL过程;

5)长期保存的原始数据管理;

6)数据湖架构中的视图映射。


与内部表相比,外部表适合原始数据、共享数据和持久化数据场景,而内部表更适合临时数据和中间结果。


关键区别在于:内部表删除时会连带删除数据,外部表仅删除元数据。


外部表(EXTERNAL_TABLE)的具体使用场景有哪些


外部表的核心价值:数据独立于 Hive 存在

一句话理解:外部表让 Hive 可以"借用"HDFS 上已有的数据,删除 Hive 表时不会删掉原始数据。


一、外部表 vs 内部表快速回顾

对比项 内部表(MANAGED_TABLE) 外部表(EXTERNAL_TABLE)
数据所有权 Hive 管理 外部程序管理
DROP TABLE 删除元数据 + 删除 HDFS 数据 只删除元数据,HDFS 数据保留
TRUNCATE ✅ 可以清空 ❌ 不允许
适用场景 临时表、中间结果 共享数据、原始数据

二、外部表的具体使用场景

场景1:数据被多个引擎共享

问题:同一份数据,Hive 要用,Spark 要用,Presto 也要用。

text

复制代码
┌─────────────────────────────────────────────────────────┐
│              HDFS 上的原始数据(/data/logs/)            │
└─────────────────────────────────────────────────────────┘
         ↓              ↓              ↓
    ┌────────┐    ┌────────┐    ┌────────┐
    │  Hive  │    │ Spark  │    │Presto  │
    └────────┘    └────────┘    └────────┘

解决方案:创建外部表

sql

复制代码
-- 多个引擎共用同一份数据,创建外部表
create external table logs(
    log_time string,
    user_id int,
    action string
)
partitioned by (dt string)
location '/data/logs/';   -- 指定 HDFS 上的数据位置

好处:如果 Hive 中删除了这个表,其他引擎(Spark、Presto)还能正常使用数据。


场景2:数据由外部系统生产

问题:数据是通过 Flume、Logstash 等工具实时写入 HDFS 的。

bash

复制代码
# Flume 实时写入日志到 HDFS
/data/flume/events/2024-01-01/event_0001.avro
/data/flume/events/2024-01-01/event_0002.avro
/data/flume/events/2024-01-02/event_0001.avro

解决方案:用外部表读取这些数据

sql

复制代码
create external table events(
    event_id string,
    event_type string,
    user_id int,
    event_time timestamp
)
partitioned by (dt string)
stored as avro
location '/data/flume/events/';

好处

  • Hive 可以随时查询这些数据

  • Flume 可以继续写入,互不干扰

  • 误删 Hive 表不会影响 Flume 的数据采集


场景3:数据已经是特定目录结构

问题:ETL 团队已经按规范把数据存放在 HDFS 上,目录结构是固定的。

text

复制代码
/data/
├── sales/
│   ├── 2024-01-01/
│   │   └── sales.parquet
│   ├── 2024-01-02/
│   │   └── sales.parquet
│   └── 2024-01-03/
│       └── sales.parquet

解决方案:创建外部表,直接映射已有目录

sql

复制代码
create external table sales(
    order_id string,
    amount double,
    user_id int
)
partitioned by (dt string)
stored as parquet
location '/data/sales/';

-- 添加已有分区
alter table sales add partition(dt='2024-01-01') location '/data/sales/2024-01-01/';
alter table sales add partition(dt='2024-01-02') location '/data/sales/2024-01-02/';
alter table sales add partition(dt='2024-01-03') location '/data/sales/2024-01-03/';

场景4:数据需要被清洗后重新存储

问题:原始数据是 JSON 格式,需要清洗后存成 Parquet 格式。

sql

复制代码
-- 1. 外部表:指向原始 JSON 数据(只读)
create external table raw_logs(
    log string
)
location '/data/raw/json_logs/';

-- 2. 内部表:存储清洗后的结果
create table cleaned_logs(
    log_time timestamp,
    user_id int,
    action string
)
stored as parquet;

-- 3. 清洗数据
insert into cleaned_logs
select 
    get_json_object(log, '$.time') as log_time,
    get_json_object(log, '$.user_id') as user_id,
    get_json_object(log, '$.action') as action
from raw_logs;

好处

  • 原始数据(外部表)永远保留,可以重新清洗

  • 清洗后的数据(内部表)可以随时删除重建


场景5:数据生命周期管理

问题:原始数据要保留很久(如 3 年),但 Hive 表可能随时重建。

sql

复制代码
-- 原始数据用外部表,永远不删数据
create external table raw_order(
    order_id string,
    order_time timestamp,
    amount double
)
partitioned by (year int, month int)
location '/data/raw/order/';

sql

复制代码
-- 应用层用内部表,删了也不影响原始数据
create table app_order as
select order_id, order_time, amount
from raw_order
where amount > 100;

好处

  • 原始数据(外部表):只读、永久保留、多团队共享

  • 临时数据(内部表):用完就删,不占空间


场景6:Hive 表只是数据湖的"视图"

问题:公司数据湖已经有完善的数据目录,Hive 只是其中一个查询引擎。

text

复制代码
数据湖(HDFS/S3)目录结构:
/s3/company/
├── bronze/    # 原始数据
├── silver/    # 清洗后数据
└── gold/      # 聚合后数据

解决方案:用外部表映射各个层级

sql

复制代码
-- 青铜层(原始数据)- 外部表
create external table bronze_clickstream(...) location '/s3/company/bronze/clickstream/';

-- 白银层(清洗后)- 外部表
create external table silver_user_behavior(...) location '/s3/company/silver/user_behavior/';

-- 黄金层(聚合结果)- 外部表或内部表
create external table gold_daily_stats(...) location '/s3/company/gold/daily_stats/';

三、什么时候用内部表?

场景 推荐 原因
临时表 内部表 用完就删,不保留数据
中间结果 内部表 ETL 过程中间表,不需要持久化
测试表 内部表 测试完直接删除,不留垃圾数据
数据不共享 内部表 只有 Hive 用,其他引擎不需要

四、什么时候用外部表?

场景 推荐 原因
原始数据 外部表 不能因为删表而丢失原始数据
多引擎共享 外部表 Hive、Spark、Presto 共用的数据
外部系统写入 外部表 Flume、Kafka、Spark Streaming 写入的数据
已有目录结构 外部表 数据已经存在,Hive 只是读取
数据湖架构 外部表 数据独立于查询引擎
长期保存的数据 外部表 数据生命周期比 Hive 表长

五、课堂笔记中的练习解读

sql

复制代码
-- 练习:创建外部表
create external table t_waibu(id int)
row format delimited fields terminated by '\t';

这个场景是什么意思?

外部表 t_waibu 的数据文件应该在 HDFS 上的某个已有位置。如果没有指定 location,数据会存在默认的 /user/hive/warehouse/ 下,但 drop table 时仍然只删元数据,不删数据文件。

真实场景 :假设你有一个生产系统每天往 /data/prod/ 目录写入数据,你可以:

sql

复制代码
create external table prod_data(
    id int,
    name string,
    value double
)
location '/data/prod/';

然后 Hive 就能查询这些数据,删除 Hive 表不影响生产系统的数据写入。


六、总结对比表

对比项 内部表 外部表
数据来源 Hive 自己创建和写入 已有数据,Hive 只是引用
删除表 数据 + 元数据 都删 只删元数据,数据保留
Truncate ✅ 允许 ❌ 不允许
适用场景 临时表、中间结果、测试 原始数据、共享数据、数据湖
生产环境推荐 ETL 中间表 原始数据层(ODS、DWD)

七、一句话记忆

内部表:Hive 拥有数据,删表就删数据
外部表:Hive 借用数据,删表不删数据

相关推荐
It's Q3 小时前
Hive序列函数&&排名函数
数据仓库·hive·hadoop
Irene19911 天前
Windows 11 WSL Ubuntu 环境:实际安装 Hive 踩坑实录
hive·windows·ubuntu
Irene19911 天前
(课堂笔记)Hive 分区、分桶与数据倾斜
hive·hadoop
Irene19912 天前
在 WSL Ubuntu 上安装和使用 Hive
linux·hive·ubuntu
Irene19912 天前
(课堂笔记)Hive 基础
hive·hadoop
水火既济__3 天前
加快hive效率
数据仓库·hive·hadoop
lifewange5 天前
Hive 数据库 增删改 完整操作指南
数据库·hive·hadoop
WL_Aurora5 天前
Sqoop数据迁移工具从入门到精通
hive·hadoop·sqoop
小的~~7 天前
CentOS7安装CDH6.3.2
hive·hdfs·kafka