☰
Hive-DDL:数据库与表操作,内部表vs外部表一文讲透
2026/10/14 4:23:52 网站建设 项目流程

Hive 从入门到实战(二):DDL 数据库与表操作,内部表 vs 外部表一文讲透

这是《Hive 从入门到实战》系列第 2 篇。上一篇装好了 Hive,这一篇解决:库和表怎么建、怎么改、怎么删,以及面试必考的内部表 vs 外部表。

目录

  • 一、数据库操作:增删改查
  • 二、建表语法全景:把每块积木拆给你看
  • 三、内部表 vs 外部表(面试高频)
  • 四、表的复制:CTAS vs LIKE
  • 五、查看表与修改表
  • 六、删除表与清空表:drop vs truncate
  • 七、面试加餐
  • 八、总结

一、数据库操作:增删改查

1.1 创建数据库:四种方式

完整语法:

CREATE[REMOTE](DATABASE|SCHEMA)[IFNOTEXISTS]database_name[COMMENTdatabase_comment][LOCATION hdfs_path][WITHDBPROPERTIES(property_name=property_value,...)];

四种常用方式:

-- 方式1:最朴素,不指定任何东西createdatabasedb_test1;-- 方式2:指定在 HDFS 上的存储路径createdatabasedb_test2 LOCATION'/db_test2';-- 方式3:附加自定义属性(kv 键值对)createdatabasedb_test3withdbproperties('create_date'='2026-08-28');-- 方式4:加注释,方便别人看懂这个库是干嘛的createdatabasedb_test4comment'测试数据库';

小细节:IF NOT EXISTS建议永远带上——库已存在时不再报错,脚本可重复执行。

不指定 LOCATION 时,库对应的数据目录默认是:

/user/hive/warehouse/db_test1.db

也就是上一篇配置的hive.metastore.warehouse.dir下加一个.db后缀目录。

1.2 查看数据库

showdatabases;-- 列出所有库showdatabaseslike'db*';-- 模糊匹配

输出:

OK db_test1 db_test2 db_test3 db_test4 default Time taken: 0.02 seconds, Fetched: 5 row(s)

like通配符规则:*匹配任意字符,|表示"或"。

1.3 查看库详情

descdatabasedb_test3;-- 基础信息descdatabaseextendeddb_test3;-- 详细信息(含 dbproperties)

输出:

OK db_name comment location owner_name owner_type parameters db_test3 hdfs://master:9000/user/hive/warehouse/db_test3.db root USER {create_date=2026-08-28}

extended比desc database多显示自定义的 dbproperties,排查"这个库是谁建的、什么时候建的"时很有用。

1.4 修改数据库

-- 改属性alterdatabasedb_test3setdbproperties('create_date'='2026-08-29');-- 改 HDFS 路径(有坑!往下看)alterdatabasedb_test2setlocation'hdfs://master:9000/test2';

修改 LOCATION 的两个大坑(真实报错实录):

坑一:必须写完整的绝对 URI,写相对路径直接报错:

alterdatabasedb_test2setlocation'/test2';
FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. {0} is not absolute. Please specify a complete absolute uri. /test2

坑二:改完不会马上在 HDFS 上创建新目录,老目录里的数据也不会搬走。只有之后新创建的表才会落到新路径。

一句话:alter ... set location只改"户口登记",不搬家。

1.5 删除数据库:RESTRICT vs CASCADE

DROP(DATABASE|SCHEMA)[IFEXISTS]database_name[RESTRICT|CASCADE];

两种模式:

模式行为默认?
RESTRICT严格模式:库不为空就删失败是
CASCADE级联模式:把库连同里面的表一起删光否

实测:

dropdatabasedb_test1;-- 空库,直接删掉dropdatabasedb_test2;-- db_test2 里有表,报错!
FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. InvalidOperationException(message:Database db_test2 is not empty. One or more tables exist.)
dropdatabasedb_test2CASCADE;-- 连锅端,库和表全删

记忆口诀:默认 RESTRICT 不删库,CASCADE 级连连锅端。

1.6 切换数据库

usebigdata;-- 切到 bigdata 库usedefault;-- 切回默认库

不切换时建的表都进default库,建议养成先use再操作的习惯。

二、建表语法全解

2.1 完整语法

CREATE[TEMPORARY][EXTERNAL]TABLE[IFNOTEXISTS][db_name.]table_name[(col_name data_type[COMMENTcol_comment],...)][COMMENTtable_comment][PARTITIONEDBY(col_name data_type,...)][CLUSTEREDBY(col_name,...)[SORTEDBY(col_name[ASC|DESC],...)]INTOnum_buckets BUCKETS][[ROWFORMAT row_format][STOREDASfile_format]][LOCATION hdfs_path][TBLPROPERTIES(property_name=property_value,...)];

看着吓人,其实就是一个"积木清单",大部分都是可选的。逐块拆解:

积木含义不写会怎样
EXTERNAL建外部表默认建内部表(管理表)
PARTITIONED BY建分区表普通表(第 4 篇详解)
CLUSTERED BY … INTO n BUCKETS建分桶表不分桶(第 4 篇详解)
ROW FORMAT指定数据文件里行列怎么切分默认^A控制符切分,几乎必须写
STORED AS指定文件格式默认 TEXTFILE(第 5 篇详解)
LOCATION指定数据在 HDFS 的路径默认 warehouse 目录下
TBLPROPERTIES表级 kv 属性无

2.2 数据类型:基本类型 + 复杂类型

基本类型和 MySQL 差不多,重点关注几个 Hive 特色的:

TINYINT / SMALLINT / INT / BIGINT -- 整数 FLOAT / DOUBLE / DECIMAL(p,s) -- 小数,金额建议 DECIMAL BOOLEAN -- 布尔 STRING / VARCHAR / CHAR -- 字符串,Hive 更常用 STRING TIMESTAMP / DATE -- 时间

复杂类型是 Hive 的招牌,一个字段可以装"一堆值":

类型写法类比元素分隔符
ARRAYarray<string>一个字段里存一串同类型值,如朋友列表,
MAPmap<string,int>一个字段里存 kv 对,如 {语文:90},与:
STRUCTstruct<street:string,city:string>一个字段里打包多个命名字段,
UNIONTYPEuniontype<int,string>多选一-

2.3 ROW FORMAT:数据怎么被切成行列

这是建表最容易出错的地方。Hive 读 HDFS 文本文件时,全靠这些分隔符切分:

rowformat delimitedfieldsterminatedby','-- 列分隔符:每行的字段用什么隔开collection itemsterminatedby','-- array/map/struct 元素之间的分隔符mapkeysterminatedby':'-- map 中 key 和 value 的分隔符linesterminatedby'\n'-- 行分隔符

关键理解:row format是读文件时的切分规则。你的 CSV 文件用逗号分隔,建表就写fields terminated by ',';写错了,查出来的数据就"错位"了。

2.4 建表实战

-- 建库createdatabaseIFNOTEXISTSbigdata;-- 内部表(默认)createtableifnotexistsbigdata.students(id stringcomment'学号',name stringcomment'姓名',ageintcomment'年龄',sex stringcomment'性别',clazz stringcomment'班级');-- 验证:insert 一条数据insertintostudentsvalues('1500100001','施笑槐',22,'女','文科一班');

输出:

WARNING: Hive-on-MR is deprecated... Query ID = root_xxx Total jobs = 3 Launching Job 1 out of 3 ... OK Time taken: 21.336 seconds

注意:插入一条数据也要跑 MapReduce,这就是上一篇说的"Hive 不适合逐行写,适合批量分析"的直观体现。

再建一张外部表(EXTERNAL),并直接把文件 put 进它的目录:

createEXTERNALtableifnotexistsbigdata.students2(id stringcomment'学号',name stringcomment'姓名',ageintcomment'年龄',sex stringcomment'性别',clazz stringcomment'班级')rowformat delimitedfieldsterminatedby',';
# 直接用 hdfs 命令把数据丢进表目录——Hive 都不用出手hdfs dfs-putstudent.csv /user/hive/warehouse/bigdata.db/students2/

put 完立刻能查到数据!这个现象正好引出下一节的核心概念:Hive 表只是 HDFS 目录的"外壳"。

三、内部表 vs 外部表(面试高频)

3.1 先给定义,再讲规则

  • 内部表(管理表 / Managed Table):Hive完全接管这张表——元数据和 HDFS 数据都归 Hive 管
  • 外部表(External Table):Hive只接管元数据——HDFS 上的数据 Hive 只"登记",不"拥有"

类比:

  • 内部表像租房:房子(数据)的进出、退租(drop)都由你和房东(Hive)绑定,退租时家具全部搬走
  • 外部表像只登记门牌号:Hive 只知道"数据在哪个目录",数据本身别人也能放、也能读,drop 表只是撕掉登记条,数据原封不动

3.2 drop 之后的区别(亲手验证)

-- 删内部表:元数据 + HDFS 数据 一起消失droptableifexistsstudents;-- 删外部表:只删元数据,HDFS 数据还在droptablestudents2;

验证外部表的数据确实还在:

hdfs dfs-ls/user/hive/warehouse/bigdata.db/students2/# 文件 student.csv 依然存在!

口诀:内管到底,外只挂名——drop 内部表连数据一起删,drop 外部表数据原地不动。

3.3 怎么选:使用场景

场景选型理由
原始日志、业务数据(多工具共享:Spark、MapReduce 也要读)外部表防止误删源数据;数据生命周期不归 Hive 管
分析过程中的中间结果表、临时表内部表用完即删,drop 顺带清数据,不留垃圾

经验法则:越靠近源头的数据越用外部表,越靠近计算结果的数据越用内部表。

四、表的复制:CTAS vs LIKE

-- CTAS:复制表结构 + 复制表数据createtablestudents3asselect*fromstudents2;-- LIKE:只复制表结构,数据为空createtablestudents4likestudents2;

输出:

-- students3:查询有全部数据 select * from students3; -- 行数与 students2 相同 -- students4:查询是空表 select * from students4; -- 0 row

口诀:AS 连数据一起搬,LIKE 只搬个壳。

注意:CTAS 不支持外部表(not supported for external tables)。

五、查看表与修改表

5.1 查看表

showtables;-- 当前库所有表showtableslike'students*';-- 模糊查descstudents;-- 看表结构(字段)descFORMATTED students;-- 看表的详细信息(格式化展示)

desc formatted输出节选(重点看这几行):

# Detailed Table Information Table Type: MANAGED_TABLE -- 内部表;外部表显示 EXTERNAL_TABLE # Storage Information Location: hdfs://master:9000/user/hive/warehouse/bigdata.db/students InputFormat: org.apache.hadoop.mapred.TextInputFormat OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat

排查"这表是内部还是外部、数据在哪、什么格式",desc formatted一条命令全搞定。

5.2 修改表

-- ① 重命名ALTERTABLEstudentsRENAMETOstudents1;-- ② 修改表属性altertablestudents1settblproperties('create_date'='2026-08-28');-- ③ 新增列altertablestudents4addCOLUMNS(scorefloatcomment'成绩');-- ④ 更新列:改名改类型(sex 改名为 gender)altertablestudents1 changecolumnsex gender string;-- ⑤ 替换列:整表字段直接替换成新定义(危险操作,慎用)altertablestudents4REPLACECOLUMNS(id string,name string);

几点提醒:

  • Hive 没有"删除某一列"的语法,想删列只能用REPLACE COLUMNS重写整份字段清单
  • change column支持移动列位置:[FIRST|AFTER column_name]
  • 修改表只改元数据,HDFS 里的原始文件不会变,所以改列名/加列后要确认老数据能对上

六、删除表与清空表:drop vs truncate

-- drop:删表(元数据没了,内部表数据也没了)DROPTABLE[IFEXISTS]table_name[PURGE];-- truncate:只清数据,表壳和字段还在TRUNCATE[TABLE]table_name[PARTITIONpartition_spec];
truncatetablestudents3;select*fromstudents3;-- 空表,但 desc students3 结构还在

关键区别(面试常问):

对比drop tabletruncate table
表结构删除保留
数据删除清空
能否用于外部表能(数据不删)不能,只对内部表有效

为什么 truncate 对外部表无效?回想 3.1 的定义——外部表的数据不归 Hive 管,Hive 自然无权清空它。

七、面试加餐

Q1:内部表和外部表的区别?
答:内部表 Hive 完全接管元数据和数据;外部表只接管元数据。drop 内部表时元数据和 HDFS 数据一起删除,drop 外部表只删元数据、HDFS 数据保留。

Q2:什么场景用外部表?
答:多工具共享的原始数据(日志、业务抽数),防止 drop 表误删源数据;Hive 只做分析不做数据所有权管理。

Q3:drop database 会不会把表删掉?
答:默认 RESTRICT 模式下,非空库删不掉;加 CASCADE 才会级联删除库中所有表。

Q4:CTAS 和 LIKE 的区别?
答:CTAS 复制结构和数据;LIKE 只复制结构。

Q5:Hive 能删列吗?
答:没有单列删除语法,用 REPLACE COLUMNS 重写字段清单;本质只改元数据,底层文件不动。

八、总结

  1. 库操作四件套:create(带 IF NOT EXISTS)、show、desc database extended、drop(RESTRICT/CASCADE)
  2. alter ... set location只改登记不搬家,且必须写绝对 URI
  3. 建表积木:EXTERNAL / PARTITIONED BY / CLUSTERED BY / ROW FORMAT / STORED AS / LOCATION
  4. 内部表全托管,外部表只挂名:drop 行为差异是核心考点
  5. CTAS 搬结构+数据,LIKE 只搬结构;truncate 只清内部表数据

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询