hive操作数据表之DML操作

Hive DML 操作:建库、建表、改表、删表,一套 SQL 全搞定

Hive 的 DML 操作跟 MySQL 很像,但有几个关键区别:

  • 建表时要指定分隔符(不像 MySQL 已经定义好了)
  • 有内表和外表之分(删表时删不删数据,取决于类型)
  • 支持分区和分桶(大数据场景下的优化手段)

数据库操作:建库、切库、删库

数据库是表的容器,用来隔离不同业务的数据。

查看已有数据库:

show databases;

创建数据库:

CREATE DATABASE IF NOT EXISTS study_hive
COMMENT '学习 Hive 用的库'
LOCATION '/user/hive/warehouse/study_hive.db';
  • IF NOT EXISTS:库存在就不重复创建,不报错
  • LOCATION:指定库在 HDFS 上的存放位置(不指定的话默认在 /user/hive/warehouse/ 下)

切换数据库:

USE study_hive;

之后命令行提示符会变成 hive (study_hive)>,表示当前在这个库里操作。

查看数据库详情:

DESC DATABASE study_hive;
-- 输出:库名、注释、HDFS 路径、所有者

删除数据库:

-- 删空库(库里没有表)
DROP DATABASE IF EXISTS study_hive_empty;

-- 删非空库(库里还有表,强制删除)
DROP DATABASE study_hive CASCADE;

CASCADE 会连库带表一起删,操作不可逆,慎用。

创建表:核心是”列定义 + 分隔符 + 存储格式”

建表是 Hive 最常用的操作。语法跟 MySQL 类似,但多了分隔符和存储格式的配置。

基本模板:

CREATE [EXTERNAL] TABLE 表名 (
  列名1 类型 COMMENT '注释',
  列名2 类型 COMMENT '注释'
)
[PARTITIONED BY (分区列 类型)]
[ROW FORMAT DELIMITED FIELDS TERMINATED BY '分隔符']
[STORED AS 存储格式]
[LOCATION 'HDFS路径'];

一个完整的例子:

CREATE TABLE IF NOT EXISTS user_info (
  id INT COMMENT '用户ID',
  name STRING COMMENT '姓名',
  age INT COMMENT '年龄',
  city STRING COMMENT '城市'
)
COMMENT '用户信息表'
ROW FORMAT DELIMITED
  FIELDS TERMINATED BY ','      -- 列之间用逗号分隔
  LINES TERMINATED BY '\n'      -- 行之间用换行
STORED AS TEXTFILE              -- 存成文本文件
LOCATION '/user/hive/warehouse/study_hive.db/user_info';

建表时的两个关键选择:

选择 选项 说明
内表 vs 外表 EXTERNAL 关键字 外表删表不删数据,内表删表删数据
存储格式 TEXTFILE / PARQUET / ORC 文本格式方便看,列式存储查询快

内部表 vs 外部表:删表时删不删数据?

这是 Hive 新手最容易搞混的概念。

内部表(默认) 外部表(加 EXTERNAL
创建方式 CREATE TABLE ... CREATE EXTERNAL TABLE ...
数据归谁管 Hive 管 用户自己管
删除表时 删元数据 + 删数据 只删元数据,数据还在 HDFS 上
适用场景 临时表、中间表 原始数据、共享数据

什么时候用外表?

数据是别的系统生成的(比如 Flume 采集的日志),Hive 只是拿来查,删表时不能把数据删了。

什么时候用内表?

数据是 Hive 自己产生的(ETL 结果、临时表),删表时数据也不想要了。

查看表是内表还是外表:

DESC FORMATTED user_info;
-- 看 Table Type 那一行:MANAGED_TABLE = 内部表,EXTERNAL_TABLE = 外部表

查看表信息

查看当前库有哪些表:

SHOW TABLES;

查看表结构(列定义):

DESC user_info;
-- 输出列名、类型、注释

查看表的完整信息(存储格式、路径、内外表等):

DESC FORMATTED user_info;
-- 输出包括:表类型、存储格式、HDFS 路径、列信息等

修改表:改表名、加列、改列

1. 改表名:

ALTER TABLE user_info RENAME TO user_detail;

2. 加列:

ALTER TABLE user_detail ADD COLUMNS (
  gender STRING COMMENT '性别',
  register_date STRING COMMENT '注册日期'
);

3. 改列名/类型:

-- 把 id 改成 user_id
ALTER TABLE user_detail CHANGE COLUMN id user_id INT COMMENT '用户ID';

注意: 改列名不会自动改数据,新旧列名对应关系要清楚。加列后老数据的该列为 NULL,不影响历史数据。

4. 删列(不直接支持):

Hive 没有 DROP COLUMN 语法,想删列要用 REPLACE COLUMNS 覆盖:

ALTER TABLE user_detail REPLACE COLUMNS (
  user_id INT,
  name STRING
);
-- 只剩两列,其他列被"删"掉了

REPLACE COLUMNS 会改变表的元数据,但不会动 HDFS 上的数据文件。如果数据文件还有”被删列”的数据,读表时会忽略。

删除表:DROP TABLE

DROP TABLE IF EXISTS user_detail;
  • 如果是内部表:删元数据 + 删 HDFS 数据
  • 如果是外部表:只删元数据,HDFS 数据还在

删表前先用 DESC FORMATTED 看一眼类型,确认是内表还是外表,别把数据意外删了。

常用数据加载方式

建完表后要往里放数据,最常用的两种方式:

方式1:从本地文件加载

LOAD DATA LOCAL INPATH '/home/hadoop/data/user.csv'
OVERWRITE INTO TABLE user_info;
  • LOCAL:文件在本地(不加则从 HDFS 加载)
  • OVERWRITE:覆盖已有数据(不加则追加)

方式2:从另一张表插入

INSERT OVERWRITE TABLE user_info
SELECT id, name, age, city FROM raw_user;