Apache Hive 是怎样做基于代价的优化的?

本文介绍了SQL查询优化器的两种类型RBO和CBO,重点阐述Hive里的CBO。Hive在0.14版本引入CBO,解决了一些RBO无法处理的问题。文中定义了代价模型,说明了计算代价的方法,还介绍通过Analyze命令获取数据属性,以及Hive利用Calcite实现CBO的方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于代价的优化器

通常,我们把 SQL 查询优化器分为两种类型:

  • RBO(Rule Based Optimizer)

  • CBO(Cost Based Optimizer)

RBO 顾名思义,就是事先定义好一系列的规则,然后去遍历这些规则做优化。

而 CBO,自然就是根据所谓的代价去做优化,代价最小的执行计划就是最好的执行计划。

RBO 固然是好的,能解决很多问题。

640?wx_fmt=png

这是上一篇文章里的例子,一个很简单的查询,对应的执行计划是这样:

640?wx_fmt=png

通过两个常见的规则转换,就能得到下面这个更好的执行计划:

640?wx_fmt=png

RBO 好不好,很好嘛,project 和 filter 都 push down 之后不就能大大减小数据量了,性能不就好了嘛。

但是 RBO 还不够好

  • 规则是基于经验的,经验就可能是有偏的,总有些问题经验解决不了

  • 不太可能列出所有经验,事实上这些规则也确实是逐渐充实的

Hive 里的 CBO

Hive 在 0.14 版本引入了 CBO,典型的,由于 join 是 SQL 中非常影响性能的操作,所以引入之初就解决了下面几个大难题:

  • Join Ordering Optimization

  • Bushy Join Support

  • Join Simplification

很显然,我们光看名字就知道,这几个问题不是 RBO 能解决了。篇幅有限,我们只看第一类情况。

640?wx_fmt=png

这个例子来自 TPC-DS Q3,比刚才那个例子稍微复杂一点。但也就是多了一张表一起 join,再多一些过滤条件。

很显然,这个查询依然能受益于 RBO 里的 push down 规则。另外留意下,两个表过滤之后的行数是这样:

640?wx_fmt=png

下面对比下,RBO 之后的执行计划是这样:

640?wx_fmt=png

而经过 CBO 之后的执行计划是这样的:

640?wx_fmt=png

可以看到,store_sales join item 之后的结果只有 82 million 行,比默认的 store_sales join date_dim 的 14 billion 行少了一个数量级了。

不同的 join 顺序带来的性能差距是巨大的。实际的性能测试结果会更直观:

640?wx_fmt=png

640?wx_fmt=png

很显然,RBO 是没法做到这点的。没法总结出这么条规则,来判断哪个表应该放在 join 顺序的前面。

那 CBO 又是怎么做到的呢?

定义代价模型

不难看出,上面的例子中,主要是通过这么两点来判断 join 顺序的:

  • 原始表的行数

  • 过滤之后的行数

说白了,就是行要少,无论是原始数据的行,还是中间结果的行,越少性能越好。

那是不是就用行来衡量代价就够了呢?

没这么简单,因为影响性能的不只有行<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值