为何我也要说SQL Server的并行:html
这几天园子里写关于SQL Server并行的文章不少,无论怎么样,都让人对并行操做有了更深入的认识。
我想说的是:尽管并行操做可能(并非必定)存在这样或者那样的问题,可是咱们不可否认并行,仍然要利用好并行。
可是,实际开发中,某些SQL语句的写法会致使用不到并行,从而影响到SQL的执行效率
因此,本文要表达的是:咱们要利用好并行,不要让一些SQL的写法问题“抑制”了并行,让咱们享受不了并行带来的快感数据库
关于SQL Server的并行:服务器
所谓的并行,指SQL Server对于那些执行代价相对较大(这个相对跟你的设置有关)的SQL时,若是数据库服务器存在多颗CPU,
SQL Server查询引擎会采用并行的方式,也即采用多颗CPU参与整个运算过程,每颗CPU“分担”一部分计算任务,最后汇总合并各个CPU的计算的一种行为
有时候,不当的并行查询不但不会加快查询的速度,想反会拖慢查询的效率,若是采用不当的并行操做,甚至会影响到整个服务器的稳定性。
因此SQL Server 究竟在多大代价下启用并行,是由配置的,这个配置可根据具体的状况作修改,有人说这个值的单位是“秒”,貌似没见过权威的资料说过到底单位是什么,这里暂不追究
有清楚这个阈值单位的园友情不惜赐教,谢了
函数
尽管并行操做可能存在这样活着那样的问题,可是咱们不能因噎废食,利用好并行,每每老是利大于弊。
可是并非全部的执行代价较大SQL都能用到并行操做,实际开发中,有一些SQL的写法会抑制到并行操做,结果,致使整个SQL语句(存储过程)的效率上不去。
下面来举例说明。
性能
并行查询是如何变成了串行的:优化
以下是一个很是简单的查询操做,这些写法下,默认状况下开启了并行,能够看到,一共开启了8个线程来对SQL语句作计算。spa
固然这SQL的执行效率还算不错,CPU时间是622毫秒,执行总时间是130毫秒,
这里不要弄混淆了,CPU时间的633毫秒,是8个CPU一共消耗的CPU时间,大于总的执行130毫秒很正常的线程
下面建立一个很是简单的函数,code
CREATE function [dbo].[fn_justFunction](@p_date date) returns date as begin return @p_date end
这个函数并无什么实际意义,执行也很是简单,传入一个时间,返回这个时间,htm
固然这里只是为了下面的操做演示,你彻底能够说我蛋疼,我只是为了演示并行被抑制的现象
翻翻你的SQL代码,有没有相似这种写法?
而后咱们这么写这个查询,就是在查询条件上这么处理CreateDate>dbo.fn_justFunction('2015-1-1')(注意不是表的列,而是函数做用在查询条件上),
注意这个函数并不影响任何查询结果,传入的2015-1-1,返回位依旧是2015-1-1,可是这么一变化,并行就变成串行的了,
SQL执行期间只有一个CPU飚了起来,使用了到达80%左右,,与此同时其余CPU跟没事人同样,也不上来帮忙,仍是很闲
还记得上面并行操做方式执行时间是多少么?130毫秒,如今粗看起来是多少,这里是4S,也就是4000毫秒
能够看到,并行操做和串行操做的效率差异仍是很大的,对于CPU的利用也不充分(固然我不是强调必定要用满全部的CPU才算合理)
再次强调一点,这里并非在表的字段上加函数抑制了索引什么的,纯粹的影响到的是并行操做。
固然,抑制并行的写法不仅仅是在查询条件在使用函数,实际开发中,影响会更大,
由于实际业务中数据有可能会更大,SQL也可能更加复杂,这种状况可能更加难以甄别。
好比链接条件上,以下,链接条件上使用函数致使没法使用并行的状况,也是实际开发中遇到的
select * from TableA a inner join TableB b on a.id=b.id and a.Column=dbo.function(@Variable) where ***
固然抑制到并行操做的不仅仅只有这两种写法,还有可能潜在其余相似的写法也会影响到并行查询。
这就要求咱们在写SQL的时候,不但要注意不能再字段上使用函数(没法使用该字段上的索引),一样,查询条件上也尽量不要使用函数,有可能影响到并行操做。
总结起来有一下几种状况会抑制到并行的使用(之后发现再更新):
1,将函数之类的操做做用在查询条件上
好比:CreateDate>dbo.fn_justFunction('2015-1-1')
2,将函数之类的操做做用在链接条件上
好比:select * from TableA a inner join TableB b on a.id=b.id and a.Column=dbo.function(@Variable) where ***
3,强函数之类的操做做用在查询列上
好比:FunctionName(ColumnName)>55,这种状况,若是查询列上有索引,不只仅是抑制索引,还会抑制并行
如何处理并行操做被抑制的状况:
若是要解决相似这些个问题,该怎么办?
其实也很简单,建议查询条件经过函数运算以后赋值给一个变量,用变量去做为查询条件进行查询。
再次开始了愉快的并行,享受并行带来的快感。
对于链接条件上的函数处理也相似,将结果计算出来以后,保存在一个变量中,把变量写在链接条件中,
固然可能有其余办法,我暂时尚未想到。
总结:
本文经过一个简单的例子演示了并行操做被抑制的现象,说明了并行和串行在执行一个代价较大的SQL上的性能的巨大的差异
其中提到的查询方式是查询条件上由于函数的缘由抑制了并行,彻底区别于在查询列上使用函数抑制索引的状况。
并行查询能够充分调动CPU资源,以高效的方式完成查询,合理的利用并行会很大程度上提升SQL的执行效率。
为了利用好并行,在写SQL的时候,必定要注意,防止并行操做遭到抑制,给性能带来影响。
SQL优化是一个艰难而又反复的过程,即使如此,也乐在其中。
面对繁复SQL,不但要有过硬的技术,也要有足够的耐心,才能看清事物的本质。
对并行的理解还不够充分,有不对的地方但愿各位看官指出,谢谢。