阿里云数字新基建系列:云数据库架构
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.2.4 SQL Server的优化器

SQL Server的优化器往往很容易被人忽视,事实上,它可能是目前最先进的数据库优化器。在流程上,SQL Server不同于MySQL,因为它要缓存结果,所以会多一些步骤,比如绑定,会自动绑定变量。SQL Server优化器的优化过程如图1-27所示。

图1-27 SQL Server优化器的优化过程

SQL Server优化器的第一步是简化(Simplification),这一步的作用有点类似于MySQL的JOIN::prepare函数,但不同于prepare主要是展开子查询,Simplification还会重写SQL关系,只是逻辑上的,比如把子查询改写成join,改写等价关系,把join的表但没有参与谓词过滤或者没有参与返回的无效join去除,等等。

举例来说:select a.xx, b.xx from a join b on xx join c on xxx where a.xx=x and b.xx=xx,这里的c表就毫无用处,会被裁剪掉。

其实MySQL在解析(Parse)阶段也会重写SQL关系,但主要功能比较弱,而且是为了适配Performance Schema,所以前文没有提。

之后就开始计算统计信息(Derive Cardinality),初始化join。接下来开始第一次优化,更准确的说法叫探测(Exploration)。这时可能有读者会问,SQL Server会进行多次优化吗?这个问法不准确,实际上SQL Server有三种执行计划级别,分别是微计划(Trivial Plan,又称Search 0)、快速计划(Quick Plan,又称Search 1)和全计划(Full Plan,又称Search 2)。

对于特别简单的单表谓词查询,一般会直接执行search 0,默认maxdop =0,优化器的开销很小,且优化结果非常可信。对于相对复杂的SQL语句,会依次尝试各Search级别。每个Search级别都有一个预设的Hard Code阈值。例如,如果在Search 1 中找到一个总成本(Cost) 低于Search 2最小(Least)阈值的执行计划,则不会触发Search 2,优化器认为这个执行计划已经足够好了。因此,对于简单的SQL语句,一般Search 0 就能保证它的执行计划的成本低于Search 1的最小阈值。

在XML版本的执行计划中会看到相关标志,表明当前的执行计划到底是什么级别的。

在实际优化中,优化器也会遵循一些策略(Implementation Rule),即我们熟悉的三种连接方式——递归循环(Nested Loop)、哈希连接(Hash Join)和合并连接(Merge Join)、两种聚合——流式聚合(Stream Aggregate)和哈希聚合(Hash Aggregate)、两种查找方式——点查(Seek)和扫描(Scan)。而且SQL Server是支持并行执行的,所以优化器也会判断是否需要并行执行。

其他一些优化器语法变形,包括SQL Server 2019开始支持的全新的Eager Index Spool以优化新的场景,请参考微软官方手册,查看具体范例,这里不做过多介绍。总体来说,SQL Server的优化器一直在提供全新的优化思路和功能,并且有非常好的投入产出考量,是一个非常优秀的优化器。