Hive教程

Hive概述

Hive核心是将HQL转换为MapReduce程序,然后将程序提交到Hadoop群集执行。Hive的最大的魅力在于用户专注于编写HQL,Hive帮您转换成为MapReduce程序完成对数据的分析。

Hive基础架构

执行流程

  1. Metastore (元数据服务) ------ 图书馆的目录卡片
  • MySQL 原理: 数据文件(.ibd)里既有数据又有表结构定义。
  • Hive 原理: 数据只是 HDFS 上的一堆文本文件(CSV, JSON, Parquet)。Hive 怎么知道哪一列是 user_id
    • 全靠 Metastore 。它通常是一个独立的 MySQL 数据库,记录了:表A -> 对应 HDFS 路径 /data/table_a,以及 第一列是 int, 第二列是 string
  • 实战影响: 如果你删了 HDFS 文件,表还在(读的时候报错);如果你删了 Metastore 里的元数据,文件还在(变成了无主孤魂的垃圾文件)。
  1. Drver (驱动器) ------ SQL 编译器
  • 这是 Hive 的核心。它负责把你写的 HQL 解析成抽象语法树 (AST),然后优化,最后生成 执行计划 (Execution Plan)
  • 实战影响: 你需要学会看 EXPLAIN 命令,看看 Driver 把你的 SQL 翻译成了几个 MapReduce 任务。

​ 3. 执行引擎 (MapReduce / Tez / Spark) ------ 真正的苦力

  • MySQL 自己有执行线程。
  • Hive 没有自己的计算能力,它要把任务外包给计算引擎(默认是 MapReduce,现在主流是 Spark 或 Tez)。
  • 实战影响: 一个简单的 GROUP BY 操作,在底层会引发巨大的网络传输(Shuffle)。理解了这个,你就知道为什么要避免数据倾斜了。

Hive metadata

因为HDFS里存储的一般是JSON或者CSV格式的,不想MySQL数据库那样有结构,那么Hive SQL该怎么找到对应的列呢?通过metaddata

Metastore 后端通常也是一个 MySQL 数据库 。 如果你连上这个 MySQL,你会看到这几张核心表(不要在生产环境手动改它们!):

  1. TBLS : 存储表的名称、Owner、类型(Managed/External)、对应 SDS 表的 ID。
  2. DBS: 存储数据库的信息(对应 Hive 的 Database)。
  3. SDS (Storage Descriptors) : 最核心的表 。存储了 HDFS 路径 (LOCATION)、输入输出格式类名、是否压缩等。
  4. COLUMNS_V2: 存储具体的列名、类型、顺序。
  5. SERDES & SERDE_PARAMS : 存储具体的分隔符(比如 field.delim,)。

当你执行 SELECT name FROM users 时,Driver 访问 Metastore 的对话其实是这样的:

  1. Driver: "我要查 users 表。"
  2. Metastore (查询 TBLS): "有这张表,属于 default 库。"
  3. Driver: "它的 name 字段在哪?"
  4. Metastore (查询 COLUMNS_V2): "是第 2 列,类型是 String。"
  5. Driver: "文件在哪?怎么解析?"
  6. Metastore (查询 SDSSERDE_PARAMS):
    • "文件在 hdfs://.../users。"
    • "格式是 TextFile。"
    • "分隔符是逗号 , (ASCII 44)。"
  7. Driver: "收到。我生成一个任务:去那个路径读文件,按逗号切分,取第 2 块数据作为 name 返回。"

Hive SQL

SQLStructured Query Language 的缩写,中文叫 结构化查询语言

DML 是 Data Manipulation Language 的缩写,中文叫 数据操作语言

它主要用于对数据库中已有的表进行数据增删改查,也就是对**表里的记录(行)**进行操作,而不是改表结构。

DDL 是 Data Definition Language 的缩写,中文一般叫 数据定义语言

它是一类 用来定义和管理数据库结构 的 SQL 语句,主要负责"建库建表"这类操作,而不是操作表里的具体数据。

太棒了!既然你已经打通了任督二脉(架构原理),那我们现在正式开始练招(Hive SQL)。

作为后端开发,学习 Hive SQL 最痛苦的不是"学不会",而是**"习惯性动作导致的坑"**。

我们将按照 DDL (建表) -> DML (数据导入) -> DQL (查询) 的顺序,每一个环节都把你熟悉的 MySQL 和 Hive 拉出来"单挑",让你一眼看穿区别。


1. DDL 篇

这是差异最大的地方。MySQL 建表关注索引和引擎,Hive 建表关注数据的物理格式

场景:建立 users

假设数据还是那个 CSV:id, name, age, city,逗号分隔。

维度 MySQL (InnoDB) Hive (数仓标准) 根本区别
语法关键字 PRIMARY KEY, AUTO_INCREMENT, ENGINE=InnoDB ROW FORMAT, STORED AS, PARTITIONED BY Hive 无主键约束,无自增 ID。
数据与表 强绑定。建表即分配空间。 松耦合。可以先建表,再把文件指过去;或者删表留文件。 Hive 必须告诉 Driver 怎么切分这行文本。
类型 VARCHAR(255) STRING Hive 尽量用 STRING,不用指定长度。

代码对比

MySQL 写法:

复制代码
CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50),
  age INT,
  city VARCHAR(50)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Hive 写法 (标准生产环境版):

复制代码
CREATE EXTERNAL TABLE users ( -- 1. 推荐使用 EXTERNAL (外部表)
  id INT COMMENT '用户ID',
  name STRING COMMENT '姓名', -- 2. 类型直接用 STRING
  age INT COMMENT '年龄',
  city STRING COMMENT '城市'
)
COMMENT '用户基础信息表'
PARTITIONED BY (dt STRING)    -- 3. 核心:按日期分区 (MySQL很少这么写)
ROW FORMAT DELIMITED          -- 4. 告诉 SerDe 怎么解析
FIELDS TERMINATED BY ','      --    列分隔符是逗号
STORED AS TEXTFILE            -- 5. 存储格式 (生产环境常用 ORC/Parquet)
LOCATION '/data/warehouse/users'; -- 6. 指定 HDFS 路径 (可选)

🛑 避坑指南:

  1. EXTERNAL : 后端习惯 DROP TABLE 删库跑路。在 Hive 里,如果是 EXTERNAL 表,DROP 只删元数据,HDFS 数据还在。这在生产环境是保命符
  2. PARTITIONED BY : 看到 dt 了吗?它不在 (id, name...) 的定义里,但在 HDFS 上会变成 /dt=2023-11-22/ 这样的文件夹。这是 Hive 唯一的"粗粒度索引"

2. DML 篇

后端开发习惯用 INSERT 一条条插数据,这在 Hive 里是绝对禁止的。

维度 MySQL Hive 根本区别
模式 交互式写入 (OLTP) 批量导入 (Bulk Load) Hive 为了吞吐量设计,不是为了低延迟。
底层动作 写 WAL 日志,更新 B+ 树 移动文件MapReduce 写入 LOAD 仅仅是把 HDFS 上的文件 mv 到表目录下。
速度 几千条/秒 几百 MB/秒 (直接搬文件) Hive 极其擅长处理海量数据。

代码对比

MySQL 写法:

复制代码
INSERT INTO users (name, age, city) VALUES ('zhangsan', 18, 'beijing');
-- 只有少量数据这样做

Hive 写法 1:搬运文件 (最快)

复制代码
-- 假设你已经把 100GB 的 log.csv 上传到了 HDFS 的 /tmp 目录
-- 这句话瞬间完成,因为只是改了 HDFS 的文件路径元数据
LOAD DATA INPATH '/tmp/log.csv' 
INTO TABLE users 
PARTITION (dt='2023-11-22');

Hive 写法 2:清洗数据 (常用)

复制代码
-- 从临时表 A 选出数据,经过处理,覆盖写入正式表 B
INSERT OVERWRITE TABLE users PARTITION (dt='2023-11-22')
SELECT id, name, age, city 
FROM tmp_users 
WHERE dt = '2023-11-22' AND age > 0;

🛑 避坑指南:

  • 不要用 INSERT INTO ... VALUES ...:虽然 Hive 支持,但每插入一条都会生成一个小文件。几万个小文件会把 NameNode (HDFS 的主节点) 搞挂。
  • OVERWRITE : Hive 数仓为了保证幂等性,通常用 INSERT OVERWRITE。如果任务重跑,它会先清空该分区,再写入,防止数据重复。

3. DQL 篇

语法 90% 相似,但执行代价天差地别。

维度 MySQL Hive 根本区别
全表扫描 SELECT * 慢,但能接受 灾难级后果 Hive 表可能有 PB 级数据。必须加分区过滤。
去重 COUNT(DISTINCT col) 很快 极慢 (容易 OOM) 所有数据挤到一个 Reducer 去重,容易内存溢出。
LIMIT LIMIT 10 瞬间返回 可能需要启动 MapReduce 虽然新版本有 fetch task 优化,但本质仍不同。

代码对比:去重统计

场景: 统计有多少个不同的用户。

MySQL 写法:

复制代码
SELECT COUNT(DISTINCT user_id) FROM users;

Hive 写法 (优化版):

如果数据量过亿,上面的写法在 Hive 里可能会跑几个小时甚至报错。

后端思维转换: 用"多线程分组"代替"单点去重"。

复制代码
-- 1. 错误/低效写法 (数据倾斜风险)
SELECT COUNT(DISTINCT user_id) FROM users WHERE dt='2023-11-22';

-- 2. 高效写法 (MapReduce 思维)
-- 先 Group By 把数据打散到不同的 Reducer,再 Count
SELECT COUNT(1) 
FROM (
    SELECT user_id 
    FROM users 
    WHERE dt='2023-11-22' 
    GROUP BY user_id -- 这里利用了多节点并行去重
) t;

避坑指南

  • 分区过滤是强制的 :在很多公司,如果你的 SQL WHERE 里没有 dt=...,SQL 审核平台直接会拦截你的查询,不允许提交。
  • 别指望秒级响应 :在 MySQL 里你可能习惯不断试错修改 SQL;在 Hive 里,跑一次 SQL 可能要 10 分钟,所以写之前要在脑子里(或者用 EXPLAIN)先预演一遍。

总结

  1. 建表 (Create): 记得加 EXTERNAL,记得定义分隔符 ROW FORMAT,最重要的是一定要加 PARTITIONED BY
  2. 写入 (Insert): 忘掉 INSERT VALUES,使用 LOAD DATA (搬文件) 或 INSERT OVERWRITE SELECT (洗数据)。
  3. 查询 (Select): 永远带着 WHERE dt='...'。遇到 COUNT(DISTINCT) 要警惕,尝试用 GROUP BY 替代。

ORMAT,最重要的是**一定要加 PARTITIONED BY**。 2. **写入 (Insert):** 忘掉 INSERT VALUES,使用 LOAD DATA(搬文件) 或INSERT OVERWRITE SELECT(洗数据)。 3. **查询 (Select):** 永远带着WHERE dt='...'。遇到 COUNT(DISTINCT)要警惕,尝试用GROUP BY` 替代。

相关推荐
一颗宁檬不酸1 小时前
《Java Web 期末项目分享:MVC+DBUtils+c3p0 玩转数据库增删改查》——第一弹
数据仓库·hive·hadoop
丸码1 小时前
Servlet生命周期全解析
数据仓库·hive·hadoop
元拓数智12 小时前
IntaLink:破解数仓建设痛点,重塑高效建设新范式
大数据·数据仓库·人工智能·数据关系·intalink
清平乐的技术专栏14 小时前
hive中with as用法及注意事项
数据仓库·hive·hadoop
larance1 天前
spark 支持hive
hive·spark
RestCloud1 天前
实时 vs 批处理:ETL在混合架构下的实践
数据仓库·etl·cdc·数据处理·批处理·数据传输·数据同步
howard20051 天前
7.1 Hive内置函数
hive·内置函数
larance1 天前
HIVE 基础
数据仓库·hive·hadoop
wei_shuo1 天前
openEuler 25.09 实操指南:飞腾 arm64 服务器的 C 程序开发与 Hadoop 伪集群部署及性能测试
hadoop·openeuler