至此,笔者粗线条地介绍了当前主流SQL引擎是如何将CBO这么一个看似高深的技术一步一步落地的。接下来,笔者将会借用 Hive、Impala这两大SQL引擎开启CBO之后的优化效果让大家对CBO有一个更直观的理解。
3 Hive-CBO优化效果
Hive本身没有去从头实现一个SQL优化器,而是借助于Apache Calcite,Calcite是一个开源的、基于CBO的企业级SQL查询优化框 架,目前包括Hive、Phoniex、Kylin以及Flink等项目都使用了Calcite作为其执行优化器,这也很好理解,执行优化器本来就可以 抽象成一个系统模块,并没有必要花费大量时间去重复造轮子。
hortonworks曾经对Hive的CBO特性做了相关的测试,测试结果认为CBO至少对查询有三个重要的影响:Join ordering optimization、Bushy join support以及Join simplification,本文只简单介绍一下Join ordering optimization,有兴趣的同学可 以继续阅读这篇文章(HIVE 0.14 Cost Based Optimizer (CBO) Technical Overview)来更多地了 解其他两个重要影响。(下面数据以及示意图也来自于该篇文章,特此注明)
select dt.d_year,
item.i_brand_id brand_id,
item.i_brand brand,
sum(ss_ext_sales_price) sum_agg from
date_dim dt, store_sales, item where
dt.d_date_sk = store_sales.ss_sold_date_sk and
store_sales.ss_item_sk = item.i_item_sk and
item.i_manufact_id =436 and dt.d_moy =12
group by dt.d_year , item.i_brand , item.i_brand_id
order by dt.d_year , sum_agg desc , brand_id limit 10
上述Query涉及到3张表,一张事实表store_sales(数据量大)和两张维度表(数据量小),三表之间的关系如下图所示:
这里就涉及上文提到的Join顺序问题,从原始表来看,date_dime有73049条记录,而item有462000条记录。很显然,如果没有其 他暗示的话,Join顺序必然是store_sales join date_dim join item。但是,where条件中还带有两个条件,CBO会根据过滤条件对 过滤后的数据进行评估,结果如下:
根据上表所示,过滤后的数据量item明显比date_dim小的多,剧情反转的有点快。于是乎,经过CBO之后Join顺序就变成了 store_sales join item join date_dim,为了进一步确认,可以在开启CBO前后分别记录该SQL的执行计划,如下图所示:
左图是未开启CBO特性时Q3的执行计划,store_sales先与date_dim进行join,join后的中间结果数据集有140亿条。而再看右图, store_sales先于item进行join,中间结果只有8200w条。很显然,后者执行效率会更高,实践出真知,来看看两者的实际执行时间:
上图很明显的看出Q3在CBO的优化下性能将近提升了1倍,与此同时,CPU资源使用率也降低了一半左右。不得不说,TPCDS中有很多相似的Query,有兴趣的同学可以进一步深入的了解。
Impala-CBO优化效果
和Hive优化的原理相同,也是针对复杂join的执行顺序、Join的执行策略选择优化等方面进行的优化,本人使用TPC-DS对Impala 在开启CBO特性前后的部分Query进行了性能测试,测试结果如下图所示:
CBO总结
这篇文章其实很早就开始构思了,前前后后花了将近3个月时间断断续续来写,写了删、删了写,记得第二稿已经写了很多内容, 有天一大早醒来完完整整地看了一遍,发现写的东西并不是自己想要的,准确说,写的缺少那么一些些条理性,改又不好改,索性 就全删了。另一方面,也有因为当前网络上并没有太多关于CBO的完整介绍,倒是找到一些英文资料,但总感觉还是缺乏条理性, 很难理解。本文第一节重点从思维上带大家认识CBO,第二节更多的从实现的视角一步一步将整个原理粗线条地落地,第三节挑选 Hive与Impala两款产品对比介绍开启CBO之后的优化效果,使大家有一个更直观的感受。