考察点
这是 Hive 基础题里的必考题,面试官想看你有没有在生产上被 drop 表坑过、知不知道怎么保住数据。追问方向:外部表怎么建、分区表配合外部表怎么用、为什么数仓建设提倡「ODS 层用外部表」。
参考答案
内部表(Managed Table):Hive 全权托管
create table 不加 external 关键字就是内部表。Hive 认为这张表的数据归它管,表现在两个层面:
- 数据默认放在 Metastore 配置的仓库目录(一般是
/user/hive/warehouse/dbname.db/tablename),可以用 location 指定,但目录所有权属于 Hive。 - drop table 时,元数据和 HDFS 上的数据一起删除。这是内部表最大的风险点:误删一张大表,数据直接没了。生产环境一般会开回收站(
fs.trash.interval)兜底,或者对核心表加ALTER TABLE ... SET TBLPROPERTIES ('EXTERNAL'='TRUE')之类的保护策略。
内部表适合数仓内部加工层(DWD/DWS/ADS),数据由 ETL 生成,生命周期跟着表走,删表即清数据,管理简单。
外部表(External Table):只登记元数据
create external table 建的是外部表,语义完全反过来:
- drop table 只删 Metastore 里的元数据,HDFS 数据原封不动。想恢复的话,用同样的 DDL 重新建表、然后
MSCK REPAIR TABLE或ALTER TABLE ADD PARTITION把分区加回来就能查。 - location 通常指向业务数据的真实位置,比如采集程序直接写 HDFS 的目录
/data/ods/user_log/ds=20260701。Hive 只是「认了这个目录」,不管文件是谁放的。
外部表适合 ODS 层:数据由采集链路(DataX、Flume、Flink 写入)产出,Hive 只做查询入口。这样即使 Hive 出故障、表被误删,原始数据也不受影响。还有一个常见用法:一套数据多引擎共享——Hive、Spark SQL、Presto、Iceberg 迁移过渡期都读同一份 HDFS 数据,各自建自己的外部表或 catalog。
注意一个细节:外部表 INSERT OVERWRITE 会写数据,truncate 对很多版本的 Hive 不允许直接作用于外部表(会报错或需要先 ALTER TABLE ... SET TBLPROPERTIES ('external.table.purge'='true')),和内部表的行为不一致,写 DDL 时要留意。
临时表(Temporary Table):会话级的草稿纸
create temporary table 只在当前会话可见,HiveServer2 重启或会话断开就没了。它和内部表、外部表的区别不是一个层级的东西——临时表解决的是「中间结果落表」的问题:
- 复杂 SQL 拆步骤调试时,把中间结果放进临时表,下一步直接查它,不用建正式表再删。
- 多会话并行跑脚本时,同名临时表互不影响。
和临时表类似但更常用的是 CTAS(create table xxx as select ...)和物化视图。临时表适合交互式调试,正式 ETL 流水线里应该建正式的中间表,因为临时表跨会话不可见,调度系统里根本没法用。
生产选型对照
| 场景 | 选择 | 理由 |
|---|---|---|
| ODS 原始采集层 | 外部表 | 数据所有权在采集链路,删表保数据 |
| DWD/DWS 加工层 | 内部表 | ETL 产出,生命周期随表 |
| 多引擎共享同一份数据 | 外部表 | Hive 不做数据所有者 |
| 调试中间结果 | 临时表 | 会话级,不留垃圾 |
可能的追问
- 外部表 drop 后数据还在,那 insert overwrite 会覆盖 location 下别人放的文件吗? 会,Hive 写数据时按自己的命名规则落文件,overwrite 会清掉该分区目录。所以外部表的 location 目录最好专库专用,别和采集程序直接产出的目录混着写。
- 内部表和外部表能互相转换吗? Hive 3.x 起可以用
ALTER TABLE ... SET TBLPROPERTIES('EXTERNAL'='TRUE')切换,切换只改元数据属性,不动数据。 - 为什么建议对 drop 操作加防护? 生产上误删核心表的事故不少见。常见手段:HDFS 回收站、表级别权限收紧(drop 权限只给管理员)、关键表加
protection属性禁止 drop。