初学Hive

前言

聊到大数据处理,Hadoop 是绕不开的话题,而提到 Hadoop 生态,就不得不说 Hive。这玩意儿到底是啥?简单来说,Hive 就是一个能让你用类似 SQL 的语言(叫 HQL)去查 HDFS 上海量数据的工具。对于熟悉 SQL 的人来说,这极大降低了数据分析的门槛,不用上来就手写复杂的 MapReduce 程序了。

但这并不意味着 Hive 是万能的。它跑的是 MapReduce(或者 Tez、Spark),天生就是为批处理设计的,所以别指望它能有毫秒级的实时查询响应,那不是它的活。

Hive 能干啥?

Hive 本身不存储数据,它更像一个数据目录和查询引擎。它能处理的数据和文件类型其实非常灵活:

  • 数据源: 主要处理存储在 HDFS 上的结构化或半结构化数据。
  • 文件格式: 默认可以直接加载文本文件(TEXTFILE),你只需要在建表时告诉 Hive 数据的列分隔符和行分隔符。除此之外,它也支持更高效的列式存储格式,如 ORCParquet,以及 SequenceFileRCFile 等。用好这些格式对性能提升有很大帮助。

核心思想是 **”Schema on Read”**。数据可以就是一堆普普通通的文本文件,在你查询的时候,Hive 才根据表的定义(元数据)来解析这些文件,而不是在写入时就强制校验格式。

运行架构

Hive 的架构可以拆成客户端和服务端两部分。我们可以用下面这张图来理解它的核心组件:

服务端组件 (Server-side Components):

  • Driver: 这是 Hive 的大脑,负责把你的 HQL 搞定。它里面又包含几个小弟:
    • Complier (编译器): 把 HQL 语句解析成语法树,然后生成一个执行计划。
    • Optimizer (优化器): 对执行计划进行优化,比如怎么做 Join 更快。
    • Executor (执行器): 把最终的执行计划交给 Hadoop 去运行。
  • Metastore (元数据存储): 这是 Hive 的核心,存着所有表的信息,比如表名、列、数据类型、分区信息、数据在 HDFS 的哪个位置等等。它通常会用一个正经的关系型数据库(比如 MySQL)来存这些信息,保证稳定可靠。把 Metastore 独立出来,也让 Hive 变得更健壮。
  • Thrift Server: 这玩意儿提供了一个 RPC 接口,让各种语言(Java, Python 等)的客户端都能远程连接到 Hive 并提交查询。

客户端组件 (Client-side Components):

  • CLI (命令行接口): 就是我们最常用的 hive 命令,直接在终端里写 HQL。
  • JDBC/ODBC: 提供了标准的数据库连接方式,让 BI 工具或者 Java 程序能像连 MySQL 一样连接 Hive。
  • Web GUI: 提供一个网页界面来操作 Hive。

一次查询的执行流程

当我们敲下一行 HQL 回车后,背后发生了什么?

简单总结一下步骤:

  1. 客户端把 HQL 发给 Driver。
  2. Driver 里的编译器和优化器开始工作,它们会去 Metastore 查询这张表到底长啥样(比如字段、分区),然后生成一个最优的执行计划。
  3. 执行器拿到计划,把它翻译成一个或多个 MapReduce(或 Tez/Spark)作业。
  4. 执行器把这些作业扔给 Hadoop 的 YARN 去调度执行。
  5. 作业在 Hadoop 集群上运行,从 HDFS 读取数据进行计算。
  6. 计算结果可能会写回 HDFS,或者直接返回给客户端。

数据模型

Hive 是怎么组织数据的呢?主要有这么几个概念:

  • Database: 和传统数据库一样,就是个命名空间,用来组织和隔离表。
  • Table: 表。分为两种:
    • 内部表 (Managed/Internal Table): Hive 全权管理。数据会被移动到 Hive 的数据仓库目录(通常是 /user/hive/warehouse)。你 DROP 这张表的时候,它的元数据和 HDFS 上的数据文件会一起被删掉。适合存放只给 Hive 用的临时表或中间表。
    • 外部表 (External Table): Hive 只管理元数据,数据文件存放在你指定的 HDFS 路径下。DROP 外部表时,只会删除元数据,HDFS 上的文件安然无恙。这对于多工具(比如 Spark、Presto 也会用)共享数据源的场景非常有用。
  • Partition (分区): 这是 Hive 一个非常重要的性能优化机制。你可以根据一个或多个列的值把一张表的数据分成不同的部分来存储。在文件系统层面,每个分区就是一个独立的文件夹。
    • 比如,一张日志表 logs 按天分区(dt 列),那么 dt='2023-10-27' 的所有数据都会存放在 HDFS 的 .../logs/dt=2023-10-27/ 目录下。
    • 当你查询时带上 WHERE dt='2023-10-27',Hive 就只需要扫描这个文件夹下的数据,而不用全表扫描,速度自然就快了。
  • Bucket (分桶): 如果说分区是”宏观”上的切分(分文件夹),那分桶就是”微观”上的切分(分文件)。它会在一个分区内,根据某列的哈希值把数据再切分成固定数量的文件(桶)。这对于高效的采样(sampling)和某些 Join 操作有奇效。

常用数据类型

Hive 的数据类型跟标准 SQL 差不多。

  • 基本类型:
    • 数值型: TINYINT, SMALLINT, INT, BIGINT, FLOAT, DOUBLE, DECIMAL
    • 布尔型: BOOLEAN
    • 字符串: STRING, VARCHAR, CHAR
    • 时间戳: TIMESTAMP, DATE
  • 复杂类型:
    • ARRAY<data_type>: 数组,比如 ARRAY<STRING>
    • MAP<primitive_type, data_type>: Key-Value 对,比如 MAP<STRING, INT>
    • STRUCT<col_name: data_type, ...>: 结构体,可以把多个字段包在一起,类似 C 语言的 struct。比如 STRUCT<name:STRING, age:INT>

Hive 与 HDFS 的关系

最后再捋一捋 Hive 和 HDFS 的关系:

  • **Hive 是”上层建筑”,HDFS 是”经济基础”**。
  • 数据存储: Hive 不负责存数据,它表里的数据实际上都是 HDFS 上的文件。Hive 的元数据(Metastore)里记录了表的数据对应 HDFS 的哪个路径。
  • 数据处理: Hive 把用户的 HQL 查询转换成底层的计算任务(如 MapReduce),这些任务在 Hadoop 集群上运行,直接操作 HDFS 上的数据文件。

所以,你可以把 Hive 理解成一个翻译官 + 指挥官。它把我们写的 SQL “翻译” 成 Hadoop 能听懂的语言(MapReduce 作业),然后 “指挥” Hadoop 集群去 HDFS 上搬砖干活。