Hive 极简入门 — 用 SQL 玩转大数据仓库,看完这篇就够了

写 MapReduce 太累了。从一个需求到产出,需要编写 Mapper、Reducer、Runner 三个类,编译打包提交。如果每个统计分析都这么搞,数据分析师可以直接辞职了。Hive 的出现,让这一切变得简单——你只需要写 SQL,Hive 帮你翻译成 MapReduce。


一、开篇:从"为什么要用 SQL 查大数据"说起

1.1 数据仓库的诞生

在 Hive 出现之前(大约 2010 年前),Hadoop 的使用方式是:

写 Java MapReduce 程序 → 编译 Jar → 提交到集群 → 等待结果 → 查看输出

完成一个简单的"统计日活跃用户"的需求,一个熟练的 Java 工程师可能需要半天到一天

Facebook 每天有海量的日志需要分析,他们发现一个问题:公司里会 SQL 的人远远多于会 MapReduce 的人。

于是 Facebook 开发了 Hive——一个能将 SQL 语句自动翻译成 MapReduce 任务 的工具。

1.2 Hive 本质上是什么?

Hive 是基于 Hadoop 的数据仓库工具,它可以将结构化的数据文件映射为一张数据库表,将 SQL 语句转换为 MapReduce 任务来执行。

  • 不存储数据:数据还是在 HDFS 上
  • 不执行计算:计算还是 MapReduce(后来也支持 Tez、Spark)
  • 只做一件事:把 SQL 翻译成 MapReduce 任务

二、数据仓库基础概念

2.1 什么是数据仓库?

数据仓库(Data Warehouse)是一个面向主题的、集成的、随时间变化的、相对稳定的数据集合,用于支持企业或组织的决策分析处理。

拆解这个定义中的四个关键词:

关键词含义举例
面向主题按业务主题组织数据,而非按应用流程订单主题、用户主题、商品主题
集成的数据来自多个系统,经过清洗、统一格式把不同系统的同一字段名统一、度量单位统一
随时间变化保存历史数据,支持时间维度的分析可以查去年同期的销售额
相对稳定数据主要是批量导入和查询,不频繁修改写入后很少改,主要是读

2.2 数据仓库 vs 传统数据库

对比维度数据仓库(OLAP)传统数据库(OLTP)
主要操作查询分析(读多写少)增删改查(读写均衡)
数据量TB ~ PB 级GB ~ TB 级
响应时间秒 ~ 分钟毫秒级
设计目标分析决策事务处理
历史数据保留多年历史通常只保留近期
数据模型星型/雪花模型(多维)实体关系模型(3NF)

2.3 数据仓库的四层架构

                   数据仓库四层架构

数据源层
  ├── 操作数据库(MySQL/Oracle 等业务库)
  ├── 文档资料(Excel、CSV)
  └── 外部信息源(第三方 API、日志文件)
       │
       ▼  ETL 过程
数据存储及管理层
  ├── 抽取(Extract)— 从各数据源获取
  ├── 转换(Transform)— 清洗、去重、格式化
  └── 装载(Load)— 加载到数据仓库
       │
       ▼
OLAP 服务器
  └── 按多维数据模型重组 → 支持多角度、多层次分析
       │
       ▼
前端工具
  ├── 数据查询(SQL 查询)
  ├── 数据报表(可视化图表)
  ├── 数据分析(即席分析)
  └── 数据挖掘(预测建模)

2.4 数据模型:星型 vs 雪花

星型模型(Star Schema)
                        ┌──────────────┐
                        │  时间维度表    │
                        └──────┬───────┘
                               │
┌──────────────┐        ┌──────┴───────┐        ┌──────────────┐
│  用户维度表   │◄───────│   事实表     │───────►│  商品维度表   │
│              │        │ (销售额等)   │        │              │
└──────────────┘        └──────┬───────┘        └──────────────┘
                               │
                        ┌──────┴───────┐
                        │  地区维度表    │
                        └──────────────┘
  • 特点:中间一张事实表(Fact Table),周围放射状连接多个维度表(Dimension Table)
  • 优点:查询性能好(一次 JOIN 即可关联所有维度)——适合查询优先场景
  • 缺点:数据冗余(维度表没有进一步规范化)
雪花模型(Snowflake Schema)
                        ┌──────────────┐
                        │  时间维度表    │
                        └──────┬───────┘
                               │
┌──────────────┐        ┌──────┴───────┐        ┌──────────────┐
│  用户维度表   │◄───────│   事实表     │───────►│  商品维度表   │
│      │       │        └──────────────┘        │      │       │
│      ▼       │                                 │      ▼       │
│  用户分类表   │                                 │  商品分类表   │
└──────────────┘                                 └──────────────┘
  • 特点:维度表进一步分解为子维度表(规范化到 3NF),形状像多个雪花连接
  • 优点:减少数据冗余,节省存储空间
  • 缺点:查询时需 JOIN 更多表,性能略低

简单记忆:星型——“一次 JOIN,全部关联”;雪花——“多 JOIN 几次,但更省空间”。


三、Hive 核心概念

3.1 Hive 体系架构

                   Hive 系统架构

┌─────────────────────────────────────────────────────┐
│                    用户接口                          │
│  CLI(命令行) | WebUI(Web 界面) | HiveServer2     │
└──────────────────────┬──────────────────────────────┘
                       │
┌──────────────────────▼──────────────────────────────┐
│             Thrift 跨语言服务                        │
│      (支持 Java/Python/PHP 等语言连接 Hive)         │
└──────────────────────┬──────────────────────────────┘
                       │
┌──────────────────────▼──────────────────────────────┐
│              底层驱动引擎(Driver)                    │
│                                                      │
│  SQL → SQL Parser → Compiler → Optimizer → Executor  │
│          ↓                               ↓           │
│        AST(语法树)                执行计划(DAG)     │
└──────────────────────┬──────────────────────────────┘
                       │
┌──────────────────────▼──────────────────────────────┐
│              Metastore(元数据存储)                   │
│  ┌────────────┐  ┌──────────┐  ┌──────────────────┐  │
│  │ 表的结构   │  │ 分区信息  │  │ HDFS 路径映射    │  │
│  └────────────┘  └──────────┘  └──────────────────┘  │
└─────────────────────────────────────────────────────┘

四大组件说明

组件功能说明
用户接口让用户输入 SQLCLI(命令行)、WebUI、HiveServer2(JDBC/ODBC)
Thrift 服务跨语言通信允许不同编程语言的客户端访问 Hive
底层驱动引擎SQL → MapReduce解析 SQL → 编译为执行计划 → 优化 → 执行
Metastore元数据存储存表名、字段名、字段类型、分区信息、HDFS 路径等

3.2 Hive vs MySQL — 根本差异

初学者最容易把 Hive 当成"大号 MySQL",但两者的设计哲学完全不同

对比项HiveMySQL
查询语言HQL(类 SQL)SQL
数据存储位置HDFS(分布式文件系统)本地磁盘(块设备)
数据格式用户定义(TEXTFILE/ORC/Parquet)系统决定(InnoDB 行格式等)
数据更新不支持(HDFS 只读追加)✅ UPDATE/DELETE
事务不支持(Hive 3.0 后部分支持 ACID)✅ 完整 ACID
执行延迟(秒~分钟级,每次查询转 MapReduce)(毫秒级)
可扩展性(线性扩展,上千节点)(单机瓶颈)
数据规模(PB 级)(TB 级以下)

深入理解:为什么 Hive 不支持事务和更新?

Hive 的数据存储在 HDFS 上,而 HDFS 的设计是"一次写入,多次读取"(Write Once, Read Many)。HDFS 不能随机修改文件的某个字节——只能追加或覆盖整个文件。所以 Hive 也不支持传统的行级更新和事务。

3.3 Hive 安装模式

模式元数据存储特点适用场景
嵌入模式内嵌 Derby 数据库配置最简单,但一次只能连接一个客户端个人测试
本地模式外部数据库(如 MySQL)元数据服务与 Hive 同进程,无需单独启动 Metastore 服务开发环境
远程模式外部数据库(如 MySQL)单独启动 Metastore 服务,多客户端可同时远程连接生产环境

企业常用远程模式:因为生产环境中,用户通常不能直接访问 Hive 部署的服务器,必须通过远程 Metastore 服务进行连接。


四、数据类型

4.1 基础数据类型

类型描述取值/精度
TINYINT1 字节整数-128 ~ 127
SMALLINT2 字节整数-32,768 ~ 32,767
INT4 字节整数-2³¹ ~ 2³¹-1
BIGINT8 字节整数-2⁶³ ~ 2⁶³-1
FLOAT4 字节单精度浮点数
DOUBLE8 字节双精度浮点数
DECIMAL任意精度的小数DECIMAL(10,2) 共 10 位,小数 2 位
STRING变长字符串
VARCHAR(n)变长,有长度限制
CHAR(n)定长字符串
TIMESTAMP时间戳(纳秒精度)2026-06-18 12:30:00
DATE日期2026-06-18
BOOLEAN布尔值TRUE / FALSE

4.2 复杂数据类型

类型说明举例
ARRAY有序数组,元素类型相同ARRAY(1, 2, 3)
MAP<key, value>无序键值对MAP('name', 'Tom', 'age', '20')
STRUCTname:type,...命名结构体,字段可不同类型STRUCT('Tom', 20)

建表示例(含复杂类型)

CREATE TABLE student(
    id INT,
    name STRING,
    scores ARRAY<INT>,         -- 多门成绩
    address STRUCT<city:STRING, district:STRING>,  -- 地址结构化
    subject_score MAP<STRING, INT>  -- 科目→成绩
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
COLLECTION ITEMS TERMINATED BY '_'
MAP KEYS TERMINATED BY ':';

五、数据库与表操作(DDL 详解)

5.1 数据库操作

-- 创建数据库
CREATE DATABASE IF NOT EXISTS my_db
COMMENT '我的数据库'
LOCATION '/user/hive/my_db';

-- 查看所有数据库
SHOW DATABASES;

-- 查看数据库详情
DESC DATABASE my_db;

-- 切换数据库
USE my_db;

-- 修改数据库属性
ALTER DATABASE my_db SET DBPROPERTIES ('owner' = 'admin');

-- 删除数据库(CASCADE 可删除非空数据库)
DROP DATABASE IF EXISTS my_db CASCADE;

5.2 创建数据表(完整语法)

CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[(col_name data_type [COMMENT col_comment], ...)]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type, ...)]
[CLUSTERED BY (col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO n BUCKETS]
[ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)];

各个子句详解

子句用途示例
TEMPORARY临时表(仅当前会话可见)CREATE TEMPORARY TABLE ...
EXTERNAL外部表(数据生命周期不受 Hive 管控)CREATE EXTERNAL TABLE ...
IF NOT EXISTS表已存在时不报错推荐总是加上
COMMENT注释COMMENT '用户信息表'
PARTITIONED BY分区PARTITIONED BY (city STRING)
CLUSTERED BY分桶CLUSTERED BY (user_id) INTO 4 BUCKETS
SORTED BY桶内排序SORTED BY (name ASC)
ROW FORMAT行格式(字段/集合/Map 分隔符)ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS存储格式STORED AS TEXTFILE / ORC / PARQUET
LOCATION数据在 HDFS 上的位置(仅外部表常用)LOCATION '/user/hive/warehouse/person'

六、内部表 vs 外部表(重点展开)

6.1 两者的本质区别

对比维度内部表(Managed Table)外部表(External Table)
数据目录Hive 仓库目录自定义 LOCATION 目录
数据生命周期Hive 控制——删表即删数据Hive 不管数据——删表只删元数据
谁负责创建数据Hive 自己(通过 LOAD DATA 或 INSERT)外部系统(日志系统、ETL 工具等事先放好)
适用场景清洗加工后的中间结果表直接映射外部已有数据

一句话总结

内部表:Hive 对你负责到底(管理数据生命周期,删表删数据);外部表:Hive 只看看不碰(只记录元数据,删表不删数据)。

6.2 LOCATION 的底层机制

CREATE EXTERNAL TABLE person (
    id INT,
    name STRING,
    age INT
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION '/hivedb/person';   -- ← 指向 HDFS 上的一个目录

关键点:LOCATION 必须指向一个目录,不能指向文件!

✅ 正确:LOCATION '/hivedb/person'
   Hive 会扫描这个目录下的所有文件
   
❌ 不要:LOCATION '/hivedb/person.txt'
   Hive 会把 person.txt 当目录处理,读不到数据

为什么是目录不是文件?

一张表的完整数据通常分布在多个文件中。如果 LOCATION 只能是单个文件,每次新增数据都要改表定义。指向目录,意味着该目录下的所有文件都是这张表的数据

一表一目录的最佳实践

/hivedb/
  ├── person/          ← 表 person 的数据目录
  │   ├── part-00000
  │   └── part-00001
  ├── order/           ← 表 order 的数据目录
  │   └── part-00000
  └── product/         ← 表 product 的数据目录
      └── part-00000

这样写 LOCATION 就可以精确指向每张表的专属目录,互不干扰

6.3 外部表还需要 LOAD DATA 吗?

分两种情况

场景操作说明
数据已经在 HDFS 上只需 CREATE EXTERNAL TABLE ... LOCATION '/path'创建表的一瞬间数据"加载"完成
后续有新数据需要导入也可以使用 LOAD DATA INPATH '...' INTO TABLE external_tableLOAD DATA 底层只是把文件移到 LOCATION 目录下
-- 场景 A:数据已在 HDFS
CREATE EXTERNAL TABLE log_20260618 (...) LOCATION '/logs/2026/06/18';
-- 表创建完,直接可以 SELECT * FROM log_20260618

-- 场景 B:后续追加新文件
LOAD DATA INPATH '/tmp/new_log.txt' INTO TABLE log_20260618;
-- 把 new_log.txt 移到 /logs/2026/06/18/ 目录下

七、分区表(Partition)— 按目录组织数据

7.1 为什么需要分区?

想象一张全国用户表,有 10 亿条数据。每次查询都全表扫描一次?太慢了。如果按"省份"分区,查询 where province='北京' 就只需扫描北京的文件。

分区的本质:在 HDFS 上表现为目录层次

未分区的表:
  /user/hive/warehouse/person/
      ├── data1.txt
      ├── data2.txt
      └── data3.txt
  (查询时扫描所有文件)

按省份分区的表:
  /user/hive/warehouse/person/
      ├── province=beijing/
      │      └── data.txt
      ├── province=shanghai/
      │      └── data.txt
      └── province=guangdong/
             └── data.txt
  (查询 where province='beijing' 时,只扫描 beijing 目录!)

7.2 静态分区

-- 创建分区表
CREATE TABLE t_user_p (
    id INT,
    name STRING
)
PARTITIONED BY (country STRING)   -- ★ 分区字段(不是实际数据中的字段)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

-- 加载数据到指定分区(静态分区)
LOAD DATA LOCAL INPATH '/hivedata/user_p.txt'
INTO TABLE t_user_p
PARTITION (country='USA');  -- 手动指定分区值

-- 新增分区
ALTER TABLE t_user_p ADD PARTITION (country='China')
LOCATION '/user/hive/warehouse/itcast.db/t_user_p/country=China';

-- 修改分区名
ALTER TABLE t_user_p PARTITION (country='China')
RENAME TO PARTITION (country='Japan');

-- 删除分区
ALTER TABLE t_user_p DROP IF EXISTS PARTITION (country='Japan');

7.3 动态分区

当数据量很大(比如每天几百万条),手动写分区太累了。Hive 提供了动态分区——自动根据字段值创建分区。

-- 开启动态分区
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;   -- nonstrict 允许所有分区都是动态的

-- 动态分区插入
INSERT OVERWRITE TABLE t_user_p
PARTITION (country)                               -- 只写字段名,不写具体值
SELECT id, name, country                          -- 最后一个字段作为分区字段
FROM source_table;

⚠️ 注意SELECT 语句中的最后一个字段必须是分区字段。Hive 会根据这个字段的值自动决定数据写入哪个分区目录。


八、桶表(Bucket)— 按文件组织数据

8.1 为什么需要分桶?

分区是在目录级别做切分,分桶是在文件级别做切分。

分区 = 粗粒度(按目录分),分桶 = 细粒度(按文件分)

不分桶的表(一个目录下可能有很多大文件):
  /user/hive/warehouse/person/
      ├── large_file_1.txt
      ├── large_file_2.txt
      └── large_file_3.txt

分桶的表(Hash 均匀分布到多个文件中):
  /user/hive/warehouse/person/
      ├── 000000_0  ← Hash(user_id) % 4 = 0 的数据
      ├── 000001_0  ← Hash(user_id) % 4 = 1 的数据
      ├── 000002_0  ← Hash(user_id) % 4 = 2 的数据
      └── 000003_0  ← Hash(user_id) % 4 = 3 的数据

8.2 分桶的原理

CREATE TABLE stu_buck (
    Sno INT, Sname STRING, Sex STRING, Sage INT, Sdept STRING
)
CLUSTERED BY (Sno) INTO 4 BUCKETS   -- 按 Sno 分 4 个桶
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

数据路由规则Hash(Sno) % 4 → 决定每条数据进入哪个桶文件。

8.3 ⚠️ 分桶表加载数据的特殊之处

绝对不能直接使用 LOAD DATA 加载分桶表!

-- ❌ 错误方式:LOAD DATA 只是文件搬运,不做 Hash
LOAD DATA LOCAL INPATH '/hivedata/student.txt' INTO TABLE stu_buck;

原因LOAD DATA 底层只是 HDFS 的 mv 操作——把源文件移动到目标目录。它不会逐行读取、计算 Hash、分配到不同文件。结果就是:所有数据挤在一个文件中,分桶规则彻底失效

正确方式(两步走)

-- Step 1:先用 LOAD DATA 加载到临时表
CREATE TABLE student_tmp (
    Sno INT, Sname STRING, Sex STRING, Sage INT, Sdept STRING
) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

LOAD DATA LOCAL INPATH '/hivedata/student.txt' INTO TABLE student_tmp;

-- Step 2:开启分桶,通过 INSERT ... SELECT 触发 MapReduce 计算 Hash
set hive.enforce.bucketing = true;
INSERT OVERWRITE TABLE stu_buck
SELECT * FROM student_tmp
CLUSTER BY (Sno);   -- ★ CLUSTER BY = DISTRIBUTE BY + SORT BY

INSERT ... SELECT 会触发 MapReduce 任务,在 Reduce 端对 Sno 计算 Hash 并按结果分发到 4 个桶文件中。

8.4 SORTED BY — 桶内排序有什么用?

CLUSTERED BY (Sno) SORTED BY (Sname ASC) INTO 4 BUCKETS

每个桶内的数据不仅按 Sno 分桶,还按 Sname 排序存储。这有什么用?

SMB Join(Sort Merge Bucket Join):如果两张表按相同的键分桶,并且桶内按相同键排序,JOIN 时不需要全表 Shuffle——只需顺序读取两个桶文件,用双指针归并匹配即可。性能提升巨大!


九、数据操作(DML 详解)

9.1 SELECT 完整语法

SELECT [ALL | DISTINCT] select_expr, ...
FROM table_reference
[JOIN table_other ON expr]
[WHERE where_condition]
[GROUP BY col_list]
[HAVING having_condition]
[CLUSTER BY col_list | [DISTRIBUTE BY col_list] [SORT BY col_list]]
[ORDER BY col_list]
[LIMIT N];

9.2 INSERT INTO vs INSERT OVERWRITE

操作HDFS 底层行为效果
INSERT INTO追加新文件到目录保留原有数据,新增数据
INSERT OVERWRITE先删旧文件,再写新文件覆盖原有数据
-- INTO:追加
INSERT INTO TABLE person SELECT * FROM student;

-- OVERWRITE:覆盖(目标表原有数据会被清空)
INSERT OVERWRITE TABLE person SELECT * FROM student;

导出到目录时只能用 OVERWRITE

-- 导出到本地目录
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/export/'
SELECT * FROM person;

-- 导出到 HDFS 目录
INSERT OVERWRITE DIRECTORY '/hivedb/export/'
SELECT * FROM person;

9.3 四大排序语义(重点对比)

这是 Hive 初学者最容易混淆的概念。我们用一个求 Top N 的实际案例来理解。

CASE:找出年龄最大的 5 个人
-- ❌ 错误写法
set mapred.reduce.tasks=2;
SELECT * FROM person SORT BY age DESC LIMIT 5;

为什么错?

SORT BY局部排序——每个 Reducer 内部排序,但不同 Reducer 之间不排序

Reducer 0(分到年龄较小的 50%): 年龄排前 5 → 60, 55, 50, 48, 45
Reducer 1(分到年龄较大的 50%): 年龄排前 5 → 80, 75, 70, 65, 62

最终输出 10 条(每个 Reducer 各 5 条):
  60, 55, 50, 48, 45, 80, 75, 70, 65, 62
  ↑ 这根本不是全局前 5!
✅ 正确写法
-- ORDER BY 强制全局排序(自动设为 1 个 Reducer)
SELECT * FROM person ORDER BY age DESC LIMIT 5;

ORDER BY 保证全局有序,但有一个 Reducer 的性能瓶颈。

🚀 企业级优化(两阶段聚合)

当数据量极大时,单 Reducer 可能 OOM。优化方式:

SELECT * FROM (
    -- 第一阶段:多个 Reducer 各自求局部 Top5
    SELECT * FROM person SORT BY age DESC LIMIT 5
) t
-- 第二阶段:1 个 Reducer 对局部 Top5 求全局 Top5
ORDER BY age DESC LIMIT 5;

假设原表 1 亿条,开 10 个 Reducer,第一阶段输出 50 条——第二阶段只需对这 50 条排序,压力从"1 亿条 → 1 个 Reducer"变成了"50 条 → 1 个 Reducer"

四大排序对比总结
排序方式作用范围Reducer 数量结果
ORDER BY全局排序强制 = 1结果绝对正确,但数据量大时可能 OOM
SORT BY局部排序(每个 Reducer 内)可多个每个 Reducer 内部有序,全局无序
DISTRIBUTE BY控制数据分发到哪个 Reducer可多个类似自定义分区器,常搭配 SORT BY
CLUSTER BY= DISTRIBUTE BY + SORT BY(字段相同)可多个分桶表的默认方式
-- DISTRIBUTE BY + SORT BY 可以不同字段
SELECT * FROM person
DISTRIBUTE BY dept   -- 按部门分发
SORT BY age DESC;    -- 每个部门内按年龄排序

-- CLUSTER BY = DISTRIBUTE BY + SORT BY(同一字段)
SELECT * FROM person CLUSTER BY dept;
-- 等价于:
SELECT * FROM person DISTRIBUTE BY dept SORT BY dept;

十、存储格式专题

10.1 五种存储格式对比

格式存储方式压缩比查询性能是否可读适用场景
TEXTFILE行式存储✅ 可读原始数据接入(ODS 层)
SEQUENCEFILE行式(二进制键值对)合并小文件
ORC列式存储最高最佳Hive 内部表首选
Parquet列式存储多引擎共享(Hive+Spark+Impala)
Avro行式 + Schema 自带表结构频繁变化场景

10.2 ORC vs Parquet — 怎么选?

维度ORCParquet
起源Hive 团队(来自 Hive 的列式优化)Twitter + Cloudera
Hive 兼容性⭐ 最佳(Hive 原生支持,谓词下推等优化最好)良好
跨引擎主要在 Hive 生态使用⭐ 最佳(Spark/Impala/Presto/Drill 都原生支持)
压缩比⭐ 略高
适用场景纯 Hive 环境多计算引擎混合环境

10.3 企业级最佳实践流水线

原始数据接入(CSV/JSON/日志)→ 存为 TEXTFILE 外部表
    │
    ▼  ETL 清洗(INSERT ... SELECT)
中间加工结果 → 存为 ORC 或 Parquet 内部表
    │
    ▼  HQL 分析查询
复杂报表 / 即席查询 → 在 ORC/Parquet 表上跑
-- Step 1:原始数据 TEXTFILE 外部表
CREATE EXTERNAL TABLE ods_log (
    ip STRING,
    ts TIMESTAMP,
    url STRING
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE
LOCATION '/data/raw_log/';

-- Step 2:ETL 后写入 ORC 表(查询性能提升数倍)
CREATE TABLE dwd_log_clean (
    ip STRING,
    ts TIMESTAMP,
    url STRING
)
STORED AS ORC;

INSERT OVERWRITE TABLE dwd_log_clean
SELECT * FROM ods_log WHERE url IS NOT NULL;

十一、篇末小结

Hive 核心知识梳理

Hive 知识链路:

数据仓库概念
   ├── 面向主题 / 集成 / 随时间变化 / 相对稳定
   ├── 数据仓库四层架构(数据源→ETL→OLAP→前端)
   └── 数据模型(星型 vs 雪花)
        │
Hive 架构
   ├── 用户接口 → Thrift → 驱动引擎 → Metastore
   ├── 内部表 vs 外部表(LOCATION 目录机制)
   ├── 分区表(目录层级)vs 桶表(文件 Hash)
   │
DDL 数据定义
   ├── CREATE / ALTER / DROP DATABASE / TABLE
   ├── PARTITIONED BY / CLUSTERED BY / STORED AS
   └── ROW FORMAT(分隔符定义)
        │
DML 数据操作
   ├── LOAD DATA(内部表)vs LOCATION(外部表)
   ├── INSERT INTO(追加)vs INSERT OVERWRITE(覆盖)
   ├── SELECT / JOIN / GROUP BY
   ├── ORDER BY(全局)vs SORT BY(局部)
   └── DISTRIBUTE BY / CLUSTER BY
        │
存储格式
   ├── TEXTFILE → ORC / Parquet 的优化流水线
   └── 列式存储优势(高压缩 + 谓词下推)

一句话总结

Hive = 把 SQL 翻译成 MapReduce 的工具。它让你用熟悉的 SQL 语言处理海量数据,底层自动完成分布式计算。


后记:五篇系列至此完结。从云计算与虚拟化的底层原理,到 HDFS 的存储架构,再到 MapReduce 的分布式计算,最后用 Hive 把一切封装成 SQL——这就是大数据技术体系从基础设施到上层应用的全链路。希望这五篇文章能帮你建立起清晰的知识框架。如果你有任何疑问或想深入了解某个主题,欢迎留言讨论!

更多推荐