Spark SQL的核心是Catalyst查询编译器,它将用户程序中的SQL/Dataset/DataFrame经过一系列操作,最终转化为Spark系统中执行的RDD。
SQL语句转化为具体执行计划是由SQL查询编译器决定的,同一个SQL语句可以转化成多种物理执行计划,如何指导编译器选择效率最高的执行计划,这就是优化器的主要作用。传统数据库(例如Oracle)的优化器有两种:
RBO: Rule-Based Optimization
也即“基于规则的优化器”,该优化器按照硬编码在数据库中的一系列规则来决定SQL的执行计划。只要按照这个规则去写SQL语句,无论数据表中的内容怎样、数据分布如何,都不会影响到执行计划。
基于规则优化是一种经验式、启发式地优化思路,更多地依靠前辈总结出来的优化规则,简单易行且能够覆盖到大部分优化逻辑,但是对于核心优化算子Join却显得有点力不从心。举个简单的例子,两个表执行Join到底应该使用BroadcastHashJoin 还是SortMergeJoin?当前SparkSQL的方式是通过手工设定参数来确定,如果一个表的数据量小于这个值就使用BroadcastHashJoin,但是这种方案显得很不优雅,很不灵活。基于代价优化(CBO)就是为了解决这类问题,它会针对每个Join评估当前两张表使用每种Join策略的代价,根据代价估算确定一种代价最小的方案 。
CBO: Cost-Based Optimization
也即“基于代价的优化器”,该优化器通过根据优化规则对关系表达式进行转换,生成多个执行计划,然后CBO会通过根据统计信息(Statistics)和代价模型(Cost Model)计算各种可能“执行计划”的“代价”,即COST,从中选用COST最低的执行方案,作为实际运行方案。CBO依赖数据库对象的统计信息,统计信息的准确与否会影响CBO做出最优的选择。
CBO 原理是计算所有可能的物理计划的代价,并挑选出代价最小的物理执行计划。其核心在于评估一个给定的物理执行计划的代价。物理执行计划是一个树状结构,其代价等于每个执行节点的代价总合。
每个执行节点的代价分为两个部分:
要计算每个执行节点的代价,CBO需要解决两个问题:
基于代价的优化器(Cost Based Optimizer,CBO)已经包含了Join重排的优化规则,join重排通过影响中间结果、具体join算法,从而影响join的执行效率
Join重排是一个较激进的优化规则,考虑到CBO无法完美估计数据量,打开这个规则可能会产生worst plan。
RBO | CBO | |
实现 | RBO使用一组规则来确定如何执行查询 | 为每个SQL语句提供最便宜的执行计划 |
应用 | 几乎所有都支持 | Mysql 、Oracle、SQL Server、Spark sql、Hive、Presto |
难度 | 实现容易,时间换空间 | 实现困难,空间换时间 |
参考
Spark SQL 内部原理 RBO Catalyst Rule-based optimization | 技术世界 | spark,sql,RBO,基于规则的优化,大数据,集群,消息系统,郭俊 Jason,spark 优化,大数据架构,技术世界,spark sql
Spark SQL 性能优化再进一步 CBO 基于代价的优化 | 技术世界 | CBO,基于代价的优化,spark,sql,CBO,大数据,集群,消息系统,郭俊 Jason,spark 优化,大数据架构,技术世界,spark sqlSpark SQL 内部原理 RBO Catalyst Rule-based optimization | 技术世界 | spark,sql,RBO,基于规则的优化,大数据,集群,消息系统,郭俊 Jason,spark 优化,大数据架构,技术世界,spark sql
SQL优化器原理 - Join重排-阿里云开发者社区
Spark源码--逻辑计划优化之表达式简化_wusuopuBUPT的专栏-CSDN博客
SQL优化器-RBO与CBO分别是什么 - JasonCeng - 博客园