前言html
上三篇文章咱们介绍了查看查询计划的方式,以及一些经常使用的链接运算符、联合运算符的优化技巧。多线程
本篇咱们分析SQL Server的并行运算,做为多核计算机盛行的今天,SQL Server也会适时调整本身的查询计划,来适应硬件资源的扩展,充分利用硬件资源,最大限度的提升性能。并发
闲言少叙,直接进入本篇的正题。负载均衡
技术准备高并发
同前几篇同样,基于SQL Server2008R2版本,利用微软的一个更简洁的案例库(Northwind)进行解析。post
1、并行运算符性能
在咱们平常所写的T-SQL语句,并非全部的最优执行计划都是同样的,其最优的执行计划的造成须要多方面的评估才能够,大部分根据SQL Server自己所造成的统计信息,而后对造成的多个执行计划进行评估,进而选出最优的执行方式。学习
在SQL Server根据库内容造成的统计信息进行评估的同时,还要参照当前运行的硬件资源,有时候它认为最优的方案可能当前硬件资源不支持,好比:内存限制、CPU限制、IO瓶颈等,因此执行计划的优劣还要依赖于底层硬件。测试
当SQL Server发现某个处理的数据集比较大,耗费资源比较多时,但此时硬件存在多颗CPU时,SQL Server会尝试使用并行的方法,把数据集拆分红若干个,若干个线程同时处理,来提升总体效率。大数据
在SQL Server中能够经过以下方法,设置SQL Server可用的CPU个数
默认SQL Server会自动选择CPU个数,固然不排除某些状况下,好比高并发的生产环境中,防止SQL Server独占全部CPU,因此提供了该配置的界面。
还有一个系统参数,就是咱们熟知的MAXDOP参数,也能够更改此系统参数配置,该配置也能够控制每一个运算符的并行数(记住:这里是每一个运算符的,而非所有的),咱们来查看该参数
这个并行运算符的设置数,指定的是每一个运算符的最大并行数,因此有时候咱们利用查看系统任务数的DMV视图sys.dm_os_tasks来查看,极可能看到大于并行度的线程数据量,也就是说线程数据可能超过并行度,缘由就是两个运算符从新划分了数据,分配到不一样的线程中。
这里如没特殊状况的话,建议采用默认设置最佳。
咱们举一个分组的例子,来理解并行运算
采用并行运算出了提高性能还有以下几个优势:
下面咱们来举个例子,详细的说明一下
并行计划通常应用于数据量比较大的表,小表采用串行的效率是最高的,因此这里咱们新建一个测试的大表,而后插入部分测试数据,咱们插入250000行,总体表超过6500页,脚本以下
--新建表,创建主键,造成汇集索引 CREATE TABLE BigTable ( [KEY] INT, DATA INT, PAD CHAR(200), CONSTRAINT [PK1] PRIMARY KEY ([KEY]) ) GO --批量插入测试数据250000行 SET NOCOUNT ON DECLARE @i INT BEGIN TRAN SET @i=0 WHILE @i<250000 BEGIN INSERT BigTable VALUES(@i,@i,NULL) SET @i=@i+1 IF @i%1000=0 BEGIN COMMIT TRAN BEGIN TRAN END END COMMIT TRAN GO
咱们来执行一个简单查询的脚本
SELECT [KEY],[DATA]
FROM BigTable
这里对于这种查询脚本,没有任何筛选条件的状况下,不必采用并行扫描,由于采用串行扫描的方式获得数据的速度反而比并行扫描获取的快,因此这里采用了clustered scan的方式,咱们来加一个筛选条件看看
SELECT [KEY],[DATA] FROM BigTable WHERE DATA<1000
对于这个有筛选条件的T-SQL语句,这里SQL Server果断的采用的并行运算的方式,汇集索引也是并行扫描,由于我电脑为4个逻辑CPU(实际上是2颗物理CPU,4线程),因此这里使用的是4线程并行扫描四次表,每一个线程扫描一部分数据,而后汇总。
这里总共用了4个线程,其中线程0为调度线程,负责调度全部的其它线程,因此它不执行扫描,而线程1到线程4执行了这1000行的扫描!固然这里数据量比较少,有的线程分配了0个任务,可是总得扫描次数为4次,因此这4个线程是并行的扫描了这个表。
可能上面获取的结果比较简单,有的线程任务尚未给分配满,咱们来找一个相对稍复杂的语句
SELECT MIN([DATA])
FROM BigTable
这个执行计划挺简单的,咱们依次从右边向左分析,依次执行为:
4个并行汇集索引扫描——>4个线程并行获取出前当前线程的最小数——>执行4个最小数汇总——>执行流聚合获取出4个数中的最小值——>输出结果项。
而后4个线程,每一个线程一个流聚合获取当前线程的最小数
而后,将这个四个最小值通过下一个“并行度”的运算符汇聚成一个表
而后下一个就是流聚合,从这个4行数据中获取出最小值,进行输出,关于流聚合咱们上一篇文章中已经介绍
以上就一个一个标准的多线程并行运算的过程。
上面的过程当中,由于咱们使用的并行汇集索引扫描数据,4个线程基本上是平均分摊了任务量,也就是说每一个线程扫描的数据量基本相等,下面咱们将一个线程使其处于忙碌状态,看看SQL Server会不会将任务动态的平摊到其它几个不忙碌的线程上。
咱们在来添加一个大数据量表,脚本以下
SELECT [KEY],[DATA],[PAD]
INTO BigTable2
FROM BigTable
咱们来写一个大量语句的查询,使其占用一个线程,而且咱们这里强制指定只用一个线程运行
SELECT MIN(B1.[KEY]+B2.[KEY]) FROM BigTable B1 CROSS JOIN BigTable2 B2 OPTION(MAXDOP 1)
以上代码想跑出结果,就我这个电脑配置估计少说五分钟以上,而且咱们还强行串行运算,速度可想而知,
咱们接着执行上面的获取最小值的语句,查看执行计划
SELECT MIN([DATA])
FROM BigTable
咱们在执行计划中,查看到了汇集索引扫描的线程数量
能够看到,线程1已经数量减小了近四分之的数据,而且从线程1到线程4,所扫描的数据量是依次增长的。
咱们上面的语句很明确的指定了MAXDOP为1,理论上讲只可能会影响一个线程,为何这几个线程都影响呢?其实这个缘由很简单,个人电脑是物理CPU只有两核,所谓的线程数只是超线程,因此非传统意义上的真正的4核数,因此线程之间是互相影响的。
咱们来看一个并行链接操做的例子,咱们查看并行嵌套循环是怎样利用资源的
SELECT B1.[KEY],B1.DATA,B2.DATA FROM BigTable B1 JOIN BigTable2 B2 ON B1.[KEY]=B2.[KEY] WHERE B1.DATA<100
上面的语句中,咱们在BigTable中Key列存在汇集索引,而查询条件中DATA列不存在,因此这里确定为汇集索引扫描,对数据进行查找
来看执行计划
咱们依次来分析这个流程,结合文本的执行计划分析更为准确,从右边依次向左分析
第一步,就是利用全表经过汇集索引扫描获取出数据,由于这里采用的并行的汇集索引扫描,咱们来看并行的线程数和扫描数
四个线程扫描,这里线程3获取出数据100行数据。
而后将这100行数据,从新分配线程,这里每一个线程平均分配到25行数据
到此,咱们要获取的结果已经均分红4个线程共同执行,每一个线程分配了25行数据,下一步就是交给嵌套循环链接了,由于咱们上面的语句中须要从BigTable2中获取数据行,因此这里选择了嵌套循环,依次扫描BigTable2获取数据。
关于嵌套循环链接运算符,能够参照个人第二篇文章。
咱们知道这是外表的循环数,也就是说这里会有4个线程并行执行嵌套循环。若是每一个线程均分25行,数据那么内部表就要执行
4*25=100次。
而后,执行完,嵌套扫描获取结果后,下一步就是,将各个线程执行的结果经过并行运算符汇总,而后输出
上述过程就是一个并行嵌套循环的执行流程。充分利用了四核的硬件资源。
参考文献
结语
此篇文章先到此吧,文章短一点,便于理解掌握,后续关于并行操做还有一部份内容,后续文章补充吧,本篇主要介绍了查询计划中的并行运算符,下一篇咱们接着补充一部分SQL Server中的并行运算,而后分析下咱们平常所写的增删改这些操做符的优化项,有兴趣可提早关注,关于SQL Server性能调优的内容涉及面很广,后续文章中依次展开分析。
有问题能够留言或者私信,随时恭候有兴趣的童鞋加入SQL SERVER的深刻研究。共同窗习,一块儿进步。
文章最后给出上一篇的链接
若是您看了本篇博客,以为对您有所收获,请不要吝啬您的“推荐”。