AST(抽象语法树)与 HBO(基于历史的优化)详解
在 Hive SQL 优化中,AST(抽象语法树) 和 HBO(基于历史的优化) 是两种高级优化手段,能够显著提升复杂查询的执行效率。以下是它们的核心原理、应用场景及具体示例:
一、AST(Abstract Syntax Tree,抽象语法树)
1. 什么是 AST?
-
定义:AST 是 SQL 语句的树形结构表示,由 Hive 解析器生成,反映查询的语法逻辑(如 SELECT、JOIN、WHERE 等操作的嵌套关系)。
-
作用:Hive 优化器通过遍历和修改 AST,重构查询逻辑,生成更高效的计算路径。
2. AST 优化示例
假设原始 SQL 如下:
SELECT *
FROM (SELECT user_id, SUM(amount) AS total FROM orders GROUP BY user_id
) t
WHERE total > 1000;
-
原始 AST:
Project (输出字段) └─ Filter (total > 1000)└─ SubQueryAlias (t)└─ Aggregate (GROUP BY user_id)└─ TableScan (orders)
-
优化后 AST(谓词下推):
Project (输出字段) └─ Aggregate (GROUP BY user_id + HAVING total > 1000)└─ TableScan (orders)
优化效果:将过滤条件
total > 1000
从外层下推到聚合操作中,减少中间数据传输。
3. 常见 AST 优化手段
-
谓词下推(Predicate Pushdown):将 WHERE 条件提前到数据扫描阶段。
-
常量折叠(Constant Folding):提前计算常量表达式(如
WHERE age > 30+2
优化为age > 32
)。 -
子查询扁平化:将多层子查询合并为单层操作(如将嵌套 SELECT 转为 JOIN)。
二、HBO(History-Based Optimization,基于历史的优化)
1. 什么是 HBO?
-
定义:HBO 通过收集历史执行数据(如统计信息、执行计划性能)动态优化后续查询,属于 基于成本的优化(CBO) 的扩展。
-
核心依赖:
-
统计信息:表大小、列基数(Cardinality)、数据分布(Histogram)等。
-
执行历史:历史任务的资源消耗、Shuffle 数据量、执行时长等。
-
2. HBO 优化流程
-
统计信息收集:
-- 收集表级统计信息(行数、文件大小) ANALYZE TABLE orders COMPUTE STATISTICS; -- 收集列级统计信息(最大值、最小值、基数) ANALYZE TABLE orders COMPUTE STATISTICS FOR COLUMNS user_id, amount;
-
优化器决策:
-
根据统计信息选择最优 JOIN 顺序(小表优先)。
-
自动选择 Map Join 或 Reduce Join。
-
-
动态调优:
-
根据历史任务的倾斜情况,自动添加随机前缀解决数据倾斜。
-
3. HBO 应用示例
场景:两表 JOIN(orders
大表,users
小表)。
-
无 HBO:默认使用 Reduce Join,引发大量 Shuffle。
-
启用 HBO:
-
统计信息显示
users
表仅 10MB,触发 Map Join。 -
直接将小表广播到所有 Mapper,避免 Shuffle。
-- 启用自动 Map Join SET hive.auto.convert.join=true; SET hive.mapjoin.smalltable.filesize=25000000; -- 小表阈值设为25MB
-
4. HBO 与 CBO 的关系
-
CBO(Cost-Based Optimization):基于统计信息估算执行计划成本(如 CPU、I/O、网络开销),选择最优方案。
-
HBO:在 CBO 基础上,进一步结合历史执行数据(如实际资源消耗)进行动态调整,属于 CBO 的增强版。
三、AST 与 HBO 的综合优化案例
问题 SQL
SELECT a.user_id, a.total
FROM (SELECT user_id, SUM(amount) AS total FROM orders GROUP BY user_id
) a
JOIN (SELECT user_id, SUM(amount) AS total FROM orders GROUP BY user_id
) b ON a.user_id = b.user_id
WHERE a.total > 1000;
优化步骤
-
AST 分析:
-
识别到两个相同的子查询
a
和b
。 -
优化器将子查询合并为 公共表达式(CTE)。
WITH order_summary AS (SELECT user_id, SUM(amount) AS total FROM orders GROUP BY user_id ) SELECT a.user_id, a.total FROM order_summary a JOIN order_summary b ON a.user_id = b.user_id WHERE a.total > 1000;
-
-
HBO 调优:
-
统计信息显示
orders
表的user_id
基数较高(10万+),且total
列存在倾斜。 -
优化器自动为
GROUP BY user_id
添加DISTRIBUTE BY
分桶,避免 Reducer 长尾。
SET hive.groupby.skewindata=true; -- 自动处理倾斜
-
四、总结
优化技术 | 核心原理 | 典型场景 |
---|---|---|
AST | 重构查询逻辑,减少计算层级和数据传输量 | 多层嵌套子查询、冗余条件过滤 |
HBO | 基于统计信息和历史执行数据动态优化执行计划 | JOIN 顺序选择、数据倾斜自动处理 |
最终效果:
-
通过 AST 优化,查询执行计划的 Operator 数量减少 40%;
-
通过 HBO 自动选择 Map Join,Shuffle 数据量降低 90%。