SQL 引擎作为数据库系统的三大核心模块之一,有着承上启下的作用。SQL 引擎负责承接客户端输入的 SQL 请求,并根据负载场景将 SQL 语句经过其解析、优化、执行等模块的处理后,将结果返回至客户端。
这看似简单的运行过程却涉及 SQL 引擎各模块的作用和工作原理。9月1日 19:30 内核实战教程第四期将会带你走进数据库 SQL 引擎,了解 SQL 引擎的各个知识点。同时,带你了解 OceanBase 在查询改写和查询优化方面的实践和经验。众所周知,查询改写模块是优化器的重点和难点,也是 SQL 性能调优工作者和 DBA 都需要掌握的基础知识,通过本期教程,你会学习大量的改写规则,掌握改写和优化的精髓,设计出更高效的 SQL。
此外,本期教程还有 OceanBase 技术专家带你在线解析 MiniOB select-meta 实现思路,手把手教你实战数据库内核。
本期能帮你解决什么问题?
1、「查询改写」 模块如何改写 SQL,才能对内核而言是一条“好SQL”?
2、通过编写 SQL 语句可以提升执行性能,为什么还需要查询优化器来对 SQL 进行优化?
直播内容抢“鲜”知
查询改写
为什么要改写 SQL 呢?
我们知道, 查询改写模块向来是查询优化器的重点和难点,因为 SQL 是一种描述性的语言,所以为了获取同一个查询结果,不同用户会写出不同的 SQL。查询改写的目的就是把 “用户的好 SQL” 转化为更加易于优化的 SQL。
而在查询改写的过程中,通常会面临两个挑战。
第一个挑战是正确性,正确性其实是很重要的一项指标,如果改写的 SQL 不等价,意味着返回结果可能不正确。在 OceanBase 里,工作人员每次做改写规则时,必须确定其语义上是等价的,有时需要从关系代数的角度证明改写规则是正确的,或通过大量的测试场景来保证正确性。
第二个挑战是完备性,也就是说设计的改写规则,必须足够通用,能够覆盖用户所有可能的写法。
查询改写对完整性体现在模式匹配方面,正确性体现在等价变化方面。除此之外查询改写还要注意有效性的判断。
在 OceanBase 数据库中,所有的查询改写可以分为两类。一类是基于规则的改写,总是把 SQL 往好的方向改写。其主要特点是触发这类改写总能生成更好的执行计划,这类改写算法总是有效的。
第二类是基于代价的改写,其主要特点是某些场景下改写后能生成更好的执行计划,有些场景下则不能。是否可以触发这类改写,需要优化器评估改写前和改写后 SQL 计划的代价,并根据改写是否可以降低计划代价决定改写是否触发。
在实际执行过程中,OceanBase 的查询改写框架会按照预定义的顺序,不断迭代基于规则的改写和基于代价的改写,直到收敛。
目前 OceanBase 的改写模块实现了非常多的改写规则,既包含学术届和工业界常见的改写规则,也包含了优化器开发人员从业务的实际场景中提炼出的改写规则。例如,基于规则的常量折叠、SPJ 和非 SPJ 的视图合并、连接消除等,基于代价的 Or-expansion、Group by replacement、窗口函数改写等。
查询优化
OceanBase 的物理优化器主要包含计划枚举和代价计算两部分。计划枚举可以枚举包含 Deep Tree、Bushy Tree 在内的多种计划形状,并且包含了 DP、Linear 在内的两种枚举算法。代价计算则涉及到统计信息、选择率计算和中间结果估计,以及代价模型等多方面因素的影响。
计划枚举是一个有确定性的算法。如果有三种连接方式,就会出现六个执行计划。每个执行计划都会计算代价,最终选择代价最小的执行计划。
在星型查询下,如果连接表超过 25 张,在不考虑物理算子实现、不考虑基于代价的改写、不考虑分布式优化的情况下,其逻辑执行计划就已经到了 2 亿级别。因此如何高效的枚举执行计划是查询优化面临的一个重要挑战。
在 OceanBase 里,如果基表个数小于十张,会使用动态规划算法。首先,枚举所有一张表的执行计划;然后,枚举两张表的执行计划;接着,枚举三张表的执行计划,以此类推。如果超过十张基表,在开源版本会有启发式的算法,快速收敛执行计划。
当 OceanBase 在枚举执行计划时,除了要保留代价最小的执行计划,还要保留存在 interesting order 的计划。因为存在 interesting order 的计划的序可能会被后续的算子用于消除排序。
索引(a) 的执行时间是十秒;索引(b)的执行时间也是十秒;主表的执行计划时间是五秒。此时,由于主表代价是最小的,p1 是有序索引,故保留 p1 和 p3。
当连接顺序生成完成后,优化器会依次分配其它的算子,例如 group by、窗口函数、 order by等。在分配其它算子的过程中依然遵循保留代价最小的计划和存在 interesting order 的计划的原则,直到所有算子分配完成后讲代价最低的计划作为最终的执行计划。
更多详细内容,敬请关注 9月1日 19:30 「从 0 到 1 数据库内核实战教程」官方课程。
附录:
内核实战教程第一期 | 成为内核开发者的第一步:搭建研发环境
内核实战教程第二期|带你揭开数据库存储结构的神秘面纱
内核实战教程第三期|为什么索引可以让查询变快?
课程回放
赶快扫描下方二维码进入「OceanBase 入门到实战」群
关注课程动态,和更多小伙伴一起学习进步
为帮助大家更好地学习数据库知识,结交新的朋友
未来 OceanBase Meetup 也会走到更多的城市中
大家进群后修改自己的群昵称哦【格式:姓名-城市-职位】
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。