Hive SQL 的运行机制与传统的 MySQL 等数据库完全不同,其核心在于将 SQL 查询转换成一个或多个 MapReduce(或 Tez/Spark)任务,并在 Hadoop 集群上分布式执行

下面我将详细分解 Hive SQL 语句的运行步骤,并用一个通俗的比喻帮助你理解。

核心思想:编译与执行

Hive 处理 SQL 的过程可以大致分为两个阶段:

  1. 编译阶段:将 SQL 字符串转换为 MapReduce 任务蓝图。
  2. 执行阶段:在 Hadoop 集群上执行这个 MapReduce 任务。

详细步骤分解

第 1 步:UI 提交查询

用户通过Hive 命令行JDBC/ODBC 客户端(如 Beeline)或 Hue 等工具向 Hive 提交一条 SQL 语句。

第 2 步:编译器(Compiler)进行词法、语法解析
  1. 词法分析 & 语法分析:Hive 会像所有编程语言编译器一样,将 SQL 字符串拆分成一个个的“单词”(Token),然后检查其是否符合 SQL 语法规则。例如,检查 SELECTFROM 等关键字的使用是否正确。
  2. 语义分析:检查语句的合法性。例如:
    • 查询的表 tbl 是否存在?
    • 查询的列 col 在表 tbl 中是否存在?
    • 用户是否有权限执行这个查询?
    • 这些操作会去查询 Hive Metastore
第 3 步:编译器生成逻辑执行计划

编译器会根据解析后的信息生成一个抽象语法树。然后,根据 Hive 的逻辑执行计划规则,将 AST 转换为一个逻辑执行计划。这是一个由逻辑操作符组成的树,描述了需要执行的操作,但还不涉及具体的计算引擎。

  • 常见逻辑操作符
    • TableScanOperator:扫描表,读取数据。
    • FilterOperator:执行过滤(如 WHERE 条件)。
    • JoinOperator:执行表连接(JOIN)。
    • SelectOperator:选择投影(SELECT 后面的字段)。
    • GroupByOperator:执行分组聚合(GROUP BY)。
    • ReduceSinkOperator:这是一个关键操作符,它标志着数据即将被重新分区,为后续的 ShuffleReduce 阶段做准备。
第 4 步:逻辑计划优化

编译器会应用一系列的优化规则对逻辑执行计划进行优化,目的是生成一个更高效的执行计划。

  • 谓词下推:尽早地执行过滤操作,减少后续处理的数据量。例如,将 WHERE 条件推到 JOIN 操作之前。
  • 列值裁剪:只读取查询中需要用到的列,而不是读取整行数据。这在列式存储(如 ORC, Parquet)中效果尤其显著。
  • 多路连接优化:优化多个表的 JOIN 顺序,减少中间结果集的大小。
第 5 步:编译器生成物理执行计划

优化后的逻辑计划会被转换成物理执行计划。这时,逻辑操作符会被转换为对应的物理操作符,并明确指定使用哪种计算引擎(如 MapReduce、Tez 或 Spark)。

  • 如果底层是 MapReduce,物理计划就会描述出哪些步骤在 Map 阶段执行,哪些在 Reduce 阶段执行,以及如何序列化、反序列化数据等。
  • 如果底层是 Tez,物理计划会变成一个由多个顶点和有向边组成的 DAG,描述更复杂的任务依赖关系,比 MapReduce 的效率更高。
第 6 步:执行引擎执行任务
  1. Driver:Hive 的驱动器(Driver)接收到物理执行计划。
  2. 提交任务:Driver 将物理计划提交给选定的执行引擎(如 YARN)。
  3. YARN 调度:YARN 的 ResourceManager 接收任务请求,分配 Container,并在 NodeManager 上启动 Application Master。
  4. 运行 MapReduce/Tez/Spark 任务:Application Master 根据物理计划向 ResourceManager 申请资源,并启动相应的 MapTask 和 ReduceTask(对于 MapReduce 引擎)。
    • Map 阶段:各个 Mapper 读取 HDFS 上的数据块,进行映射、过滤、排序等操作,输出中间结果。
    • Shuffle 阶段:将 Map 阶段的输出按照 Key 进行分区、排序,然后通过网络传输到对应的 Reducer 节点。
    • Reduce 阶段:各个 Reducer 对收到的数据进行最终的聚合、计算等操作,并将结果写入 HDFS。
第 7 步:获取并返回结果
  • 对于 SELECT 查询,执行引擎(如 MapReduce)会将最终结果写入一个临时文件
  • Hive Driver 会从该临时文件中读取数据,并通过 UI 返回给用户。
  • 对于 INSERT 语句,结果会直接写入目标表所在的 HDFS 路径。

一个简单的比喻

想象一下你是一家公司的老板(用户),要统计所有部门的总工资(SQL查询)。

  1. 提交需求:你写了一张需求单(SELECT dept, sum(salary) FROM employee GROUP BY dept;)交给助理(Hive UI)。
  2. 助理分析:助理(编译器)看懂你的需求后,发现需要:
    • 去档案室(HDFS)拿所有员工的档案(TableScan)。
    • 按部门分组(GroupBy)。
    • 计算每个部门的工资总和(Sum)。
  3. 制定计划:助理觉得一个个看太慢,他制定了一个并行化方案(物理计划):
    • 派一队人(Mappers)去档案室,每人负责一摞档案,分别把自己手里的档案按部门分开,并初步算出小计。
    • 再派另一队人(Reducers),第一个人只负责接收所有“销售部”的初步结果并求总和,第二个人只负责“技术部”,以此类推。
  4. 执行计划:助理把这个计划交给项目经理(YARN),项目经理去协调人力(Containers)执行。
  5. 汇总结果:最后,各个负责人(Reducers)把结果报给项目经理,项目经理汇总后交给助理,助理最终把报表(结果集)呈交给你。

总结与关键点

步骤 组件 职责
1. 提交 UI (CLI, Beeline, Hue) 接收用户查询
2-5. 编译与优化 编译器 + 元存储 解析SQL、验证元数据、生成并优化逻辑/物理计划
6. 执行 执行引擎 + YARN 分布式执行任务(MapReduce/Tez/Spark)
7. 取结果 Driver 获取结果并返回给UI
  • Hive 本身不存储和处理数据:数据存储在 HDFS 上,计算由 MapReduce/Tez/Spark 完成。Hive 只是一个“翻译官”和“调度员”。
  • 元数据是核心CREATE TABLE 这样的语句并不在 HDFS 上创建数据,只是在 Metastore(通常是 MySQL 或 PostgreSQL 数据库)中记录表的结构、位置等信息。这正是 Hive 被称为“数据仓库”工具的原因。
  • 执行引擎的演进:传统的 MapReduce 因为磁盘 I/O 过多而较慢。TezSpark 作为更现代的执行引擎,通过内存计算和更优的 DAG 调度,大大提升了 Hive 的执行速度,现在已成为主流选择。你可以通过 set hive.execution.engine=tez; 来设置。
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐