T-SQL执行内幕(5)——执行

186 篇文章 6 订阅
130 篇文章 237 订阅

本文属于SQL Server T-SQL执行内幕系列

 



    一旦优化器选择了开销最低的预估执行计划之后,就会把预估执行计划转换成实际执行树(Actual Execution Tree)进行查询执行。树的每个节点都是一个操作符。操作符及一系列的有向箭头(代表数据流的方向及结果集的数据量(箭头粗细)) 组成了整个执行计划,这里指的是图形化执行计划。

    所有的操作符都实现一个具有三个方法(open()/next()也叫GetRow()/close())的抽象接口。执行过程会循环调用包括根节点在内的每个操作符的open()方法,然后重复调用next()方法直到方法返回false,最终调用close()。

    执行树的根节点操作符会按同样的方式依次调用下级的每个子操作符,而这些子操作符又以相同方式调用自己的下级操作符,以此类推到最后级别的操作符(叶子节点)为止。然后叶子节点进行操作之后把数据返回给自己的父操作符,然后父操作符把数据处理完之后再汇总给自己的父操作符,以此类推最终把结果汇总给执行树的根节点并返回给客户端。比如下面的简单查询:


    红色箭头代表执行的方向,黄色箭头代表数据返回的方向。

    在叶子节点的操作符通常是物理访问操作符(比如上图的最右端两个聚集索引扫描),用于实际地从表和索引上查询数据。在中间结点的操作符进行一些如过滤数据、JOIN、排序等操作的数据操作符。后续小节会陆续介绍。

    性能优化的顺序通常是从叶子节点(如上图的聚集索引扫描)开始自下而上优化,因为叶子节点代表了后续要处理的数据集的量和访问数据的方式,如果过程数据非常多,不仅占用缓存和CPU等各种资源,也会在数据集关联过程明显降低性能。

    对于并行操作的查询的执行,使用一种叫Exchange操作符,这个操作符分配多个线程用于执行,然后把子树的线程结果汇总作为这个操作符的输出,是一个典型的“多生产者单消费者”模式。在并行执行的过程中,一个worker会按照服务器配置,按实际情况被拆分成多个workers,每个workers分别执行一部分的操作,然后再汇总,这种情况下最常见的两种问题就是线程间阻塞和线程间死锁。比如如果一个库有多个数据文件,而且数据文件的大小及所在的磁盘I/O非常不均匀,那么在检索数据的时候,I/O快的盘上的数据可能会很快被检索,但是由于慢盘上的线程检索慢,就会出现木桶效应,整个操作都需要等待最慢的那个线程完成为止。另外如果多线程对数据出现不合理的访问顺序及写法、索引等因素都不理想的情况下,很可能会出现死锁。这种死锁通常可以通过改进语句性能来减缓。

    这种模式(不是指并行执行)不仅用于查询,还包括数据修改(增删改),但是对于一些无法优化的语句如Insert into… values…等,会产生一个普通计划(trivial plan)。不管复杂的执行计划还是普通执行计划,执行时还是以迭代调用next()方法直到执行树完成为止。

    在各种操作符中,有些是很简单的操作符,如top(N):先对其调用open()方法,然后调用next(),由于TOP操作符必有子操作符(TOP的数据源),所以这个操作符只需要对子操作符调用next()方法并获取一个值(调用一次),直到调用完N次为止,此时top操作符会收到来自于子操作符的false消息然后停止对子树的迭代。

    但是也有一些复杂行为的操作符,如嵌套循环联接(nested loop),它需要持续跟踪关联的两表(内表和外表)的位置,对外表(图形化执行计划中处于上方的表)调用next(),然后在内表中调用next()并进行join条件的匹配,直到条件满足后进行外表的下一次调用。

    除了简单和复杂这两个分类之外,某些操作符还具有“走走停停”(stop-and-go)行为,也就是直到所有子操作符的输入处理完成之后才输出父操作符的结果,比如SORT:开始调用next()时并不会返回数据,直到所有子操作符的数据被检索并排序后,才会返回结果给sort操作符。

    有些操作符如HASH JOIN同时具有复杂和stop-and-go行为:为了创建hash表,需要调用build side(其中一个表)的next()方法直到操作符返回false,然后调用probe side(另外一个表)的next()方法直到与build side数据匹配为止,才返回数据。

    当数据检索完毕之后,在内存充足的前提下,很多相关数据会缓存到内存的数据缓存中(Data Cache),这部分是SQL Server占用内存的最大部分。也是为什么经常有人说SQL Server很吃内存的“表现”,因为数据缓存在内存中,内存的速度远超于磁盘,避免了磁盘IO的开销。从而最大化检索速度,随着技术的发展,在SQL 2014开始出现的In-Memory技术又进一步把内存速度提升到极致。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值