SQL Server 2000中的并行处理和执行计划中的位图运算符
SQL Server 2000中的并行处理和执行计划中的位图运算符
摘抄自:SQLServer 2000并行处理和位图简介 刘志斌
并行查询介绍
Degree of Parallelism(并行度)

一个查询使用并行来处理时,SQL Server为该查询分配多个线程,每个线程使用一个CPU进行操作。
Degree of Parallelism就是SQL Server为并行查询分配的线程数量,也表明这个并行查询将使用多少个CPU进行并行处理。
Exchange Oprators(交换操作)
查询语句的执行计划中,通常是并行操作和串行操作结合在一起。并行操作要求将输入数据流(data stream)切分成
多个(即degree of parallelism)部分,分别分配给各个线程进行并行处理。
并行查询包括几个数据流的交换操作(exchange operator),用以管理并行计划的执行。
Distribute Steams(分布流)

执行计划中显示为Parallelism/Distribute Steams。通常情况下,如果在一个串行操作之后紧接着一个并行操作,
则这个并行操作将从前一个串行操作接收一个input stream。
Distribute Steams就是并行查询中将单个input stream分发到多个output stream中的操作。
简述
例如一个serial table scan(串行表扫描) 产生一个4000条记录的output stream,
假设在这个table scan之后是一个并行操作,则在这两个操作之间必须需要一个Distribute Steams操作,
向并行操作的各个线程分发input stream。
如果degree of parallelism为4,SQL Server根据关键字段,将这个4000条记录的stream分发成4个大致相当的stream,
分别作为4个线程的input。 Distribute Streams操作之后,每一条input stream中的记录,将出现在某一个output stream中,
记录的内容和格式不会发生任何变化。
SQL Server自动在output stream中保留input stream中各记录的相对顺序。
示例
示例中要使用到2个表
USE [pratice]
GO
CREATE TABLE TblBuyerItem
(
UserID NVARCHAR(40) NOT NULL ,
OrgID NVARCHAR(40) NOT NULL ,
ItemID NVARCHAR(40) NOT NULL
)
CREATE CLUSTERED INDEX cix_TblBuyerItem ON TblBuyerItem(UserID,OrgID,ItemID) INSERT INTO [dbo].[TblBuyerItem] ( [UserID], [OrgID], [ItemID] )
SELECT '','',''
GO 1500000
这个表的Clustered Index:UserID,OrgID,ItemID,记录数为150万
CREATE TABLE #alert_asn_shipoverdue
(
ORG NVARCHAR(40) NOT NULL ,
ITEM NVARCHAR(40) NOT NULL ,
VENDOR NVARCHAR(40) NOT NULL
)
INSERT INTO [#alert_asn_shipoverdue] ( [ORG], [ITEM], [VENDOR] )
SELECT '','',''
GO 150
这是个临时表,没有PK,没有任何index,记录数为150
执行的SQL如下(没有使用到TblBuyerItem的Clustered Index Seek)
SELECT a.UserID
FROM TblBuyerItem a
INNER JOIN #alert_asn_shipoverdue b ON b.ORG = a.OrgID AND b.ITEM = a.ItemID
OPTION ( MERGE JOIN )
执行计划如下图

执行计划中,图标右下脚有个黄色小圆圈,里面有三个并行小箭头,则表明这个操作是并行执行的。
并行处理中的stream数据流如下图所示:

上图示例为当设置degree of parallelism为3时的执行情况。表示只能使用3个线程来执行并行操作
执行过程介绍如下:
先在#alert_asn_shipoverdue表上执行table scan,然后根据 ORG列和ITEM列的值,
将#alert_asn_shipoverdue表的数据分发到三个stream中,
假设编号分别为B1、B2、B3。三个线程各自对所获得的stream创建bitmap,然后进行排序。

接下来,三个线程并行的在TblBuyerItem表上执行Clustered Index Scan。
操作完成后每个线程获得一个output stream,
假设编号分别为A1'、A2'、A3'。
现在A1'、A2'、A3'还不能与B1 、B2、B3匹配成A1'-B1、A2'-B2、A3'-B3,
独立的进行Merge Join操作,因此根据 OrgID列和ItemID列的值,
对A1'、A2'、A3'执行Repartition Streams操作

为接下来的Merge Join重组A1'、A2'、A3',并且使用bitmap过滤记录。
假设重组后的stream分别编号为A1、A2、A3,此时,三个线程分别使用A1-B1、A2-B2、A3-B3作为输入,
执行Merge Join操作。在Merge Join操作前,两个input都必须是经过排序的,
因此每一个stream在进入Merge Join操作前都有一个Sort操作。
最后,Gather Streams操作从三个线程的output stream中收集合并记录集,得到完整的Merge Join结果记录集。


Parallel query(并行查询)并不能节约内存、CPU的资源开销,因为将stream进行Distribute、Repartition、Gather都需要消耗更多的资源。
但是Parallel query也许可以节约query的执行时间。
Bitmap(位图)
在上面的示例中,可以看到Bitmap/Bitmap Create的操作。


在MANY-TO-MANY的Join中,两个表可能存在大量不匹配的记录。
在上面的示例中,#alert_asn_shipoverdue的记录只有150,而TblBuyerItem的记录是1,500,000,
如果直接对两个表进行Merge Join,就必须为TblBuyerItem的1,500,000记录进行排序,
这是一个成本非常高的操作。而在1,500,000记录中,只有少量记录符合匹配条件。
Bitmap操作在Join操作前,快速的对数据进行一次初步的过滤,减少Join操作的开销。
Bitmap in Merge Join
仍以上面的示例来说明,在Parallelism/Distribute Streams操作之后,每个线程得到一个input stream,
接下来各个线程为自己的stream创建bitmap。我们假设分配给线程1的stream编号为B1。
Bitmap创建完成后,包含一系列0、1的值
为1的位代表对应于这一位:该stream中存在相应的记录
为0的位代表对应于这一位:该stream中不存在相应的记录
在Parallelism/Repartition Streams操作时,从input stream中循环取出每条记录,
先确定该记录应当进入哪一个output stream中。我们假设某一条记录被确定应当放入编号为A1的output stream,
这个output stream A1将与stream B1匹配,被分配给线程1,作为线程1 Merge Join的两个输入。
接下来SQL Server使用这条记录,查询与output stream A1对应的stream B1的bitmap。
如果相应的位值为0,则说明这条记录在B1中不可能存在匹配的记录,因此这条记录被忽略掉,不会放入output stream A1中;
如果相应的位值为1,则说明这条记录在B1中可能存在匹配的记录,该记录被放入output stream A1,
继续在后续的Merge Join中进行精确的匹配。
关于bitmap具体如何创建还不清楚,猜想大致应当是如下的一个过程:
使用hash算法进行操作在查询优化期间基于#alert_asn_shipoverdue的Join字段ORG、ITEM可能出现的唯一值数量而确定bitmap的大小。
这个过程和Hash Join中确定hash table buckets数量和大小有点类似。
执行期间,先使用这个bitmap大小的值创建bitmap,初始化各个位均为0。
然后为#alert_asn_shipoverdue循环,对每一个ORG、ITEM的组合值进行hash,
得到的hash value对应于bitmap中的某一个位,将这个位设为1。
基于上面bitmap的创建过程,在Parallelism/Repartition Streams操作时,
某一条记录被确定进入哪一个output stream之后,即可以找到相对应stream的bitmap。
对这条记录OrgID、ItemID的值,使用在bitmap创建时相同的hash算法,用得到的hash value查找对应的位。
下面看一下示例中bitmap的使用带来的效果

在对TblBuyerItem进行scan时,Row Count为1,543,050。
在Repartition Streams操作中,WHERE:(PROBE([Bitmap1002])=TRUE)表明对bitmap的使用,
Row Count 3,138。另外,从上图中可以看出,示例的SQL实际执行时使用了8个 CPU。
附加说明:在上面的示例中,#alert_asn_shipoverdue很小,并且bitmap的create和probe过程,
其实已经和Hash Join差不多。
事实上,让SQL Server自动选择Join Type时,使用的是Hash Join(参考[Join Type说明],使用的是同样的示例)。
使用Hash Join时用的是serial方式,耗时4秒多;上面的示例耗时2秒;
上面示例不使用并行处理(MAXDOP 1)时,耗时1分30多秒。
Merge Join中,在outer input的分支进入Merge Join前,必须有一个Sort操作,
SQLServer才能使用bitmap。
这是因为这个Sort操作使得整个outer input的分支处理完毕之后,才开始inner input分支的执行,最后再进入Merge Join操作。
这样inner input分支执行时,才能使用在outer input分支上创建的bitmap。
如果没有这个Sort操作,SQL Server会同时开始处理outer input分支和inner input分支,这样是无法使用bitmap的。
我们可以在上面的示例上做一个验证。假如在#alert_asn_shipoverdue有一个clustered index(ORG,ITEM),
那示例中的SQL语句执行时会是什么状况?
在(ORG,ITEM)上创建clustered index后

对#alert_asn_shipoverdue的Table Scan变成了Clustered Index Scan,得到的stream是按照ORG、ITEM排序的。

现在,在Parallelism/Distribute Streams操作前的stream是按ORG、ITEM排序的,
因此Distribute Streams的各个output stream也是按照ORG、ITEM排序的,
因此这个outer input分支在Merge Join前不再需要Sort操作,这样的话就无法使用bitmap了。
从执行计划图中可以看到,inner input的分支,在TblBuyerItem的Table Scan之后,箭头的大小一直到Merge Join操作没有变化,
说明在这个分支上一系列的操作中,记录数基本上没有什么变化。
下图是TblBuyerItem的Table Scan和Parallelism/Repartition Streams的
详细信息

在这个验证中,没有使用bitmap的平均执行时间是1分10秒。
Bitmap in Hash Join
Hash Join中的bitmap,总体上来讲跟Merge Join中的处理是一样的。
在build input(outer input)上构造hash table时是并行处理的,构造hash table的同时也为每个build input的stream创建bitmap。
当整个build阶段完成后,再开始probe阶段,因此在probe阶段执行时已经可以使用bitmap,
接下来的操作就跟Merge Join中Probe Bitmap操作完全一样。
SQL Server只在Parallel Query中使用bitmap,估计是Probe Bitmap结合ParallelQuery中的Repartition操作,
可节约的成本比较明显。在Serial Query中,额外的去Probe Bitmap,可能对查询的执行并不能带来明显的改善。
OK,It's over now.
下面回顾一下示例的语句在各种情况下的执行效果:

参考文章:
MSDN - Parallel Query Processing -http://msdn.microsoft.com/library/default.asp?url=/library/en-us/architec/8_ar_sa_7ujr.asp
MSDN - Bitmaps in Microsoft SQL Server 2000 -http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsql2k/html/sqlbitmaps.asp
MSDN - Logical and Physical Operators -http://msdn.microsoft.com/library/default.asp?url=/library/en-us/optimsql/odp_tun_1_1m7g.asp
SQL Server 2000中的并行处理和执行计划中的位图运算符的更多相关文章
- 配置sql server 2000以允许远程访问 及 连接中的四个最常见错误
地址:http://www.cnblogs.com/JoshuaDreaming/archive/2010/12/01/1893242.html 配置sql server 2000以允许远程访问适合故 ...
- SQL Server 2000中的完整备份、差异备份操作
在SQL Server 2000中,假定我们拥有一个数据库为:Test, 现在需要它每天19:00自动进行一次备份,并且以后一旦发生数据库错误,我们都可以通过备份文件将数据库恢复到任何一个备份过的时刻 ...
- 浅析SQL SERVER执行计划中的各类怪相
在查看执行计划或调优过程中,执行计划里面有些现象总会让人有些疑惑不解: 1:为什么同一条SQL语句有时候会走索引查找,有时候SQL脚本又不走索引查找,反而走全表扫描? 2:同一条SQL语句,查询条件的 ...
- SQL Server 执行计划中的扫描方式举例说明
SQL Server 执行计划中的扫描方式举例说明 原文地址:http://www.cnblogs.com/zihunqingxin/p/3201155.html 1.执行计划使用方式 选中需要执行的 ...
- 在Spring中配置SQL server 2000
前言 Lz主要目的是在Spring中配置SQL server 2000数据库,但实现目的的过程中参差着许多SQL server 2000的知识,也包罗在本文记载下来!(Lz为什么要去搞sql serv ...
- SQL Server 2000向SQL Server 2008 R2推送数据
[文章摘要]最近做的一个项目要获取存在于其他服务器的一些数据,为了安全起见,采用由其他“服务器”向我们服务器推送的方式实现.我们服务器使用的是SQL Server 2008 R2,其他“服务器”使用的 ...
- sql server 2000,Log.LDF文件丢失,附加数据库失败的解决办法[转]
SQL Server数据库备份有两种方式,一种是使用BACKUP DATABASE将数据库文件备份出去,另外一种就是直接拷贝数据库文件mdf和日志文件ldf的方式.下面将主要讨论一下后者的备份与恢复. ...
- MS SQL Server2014链接MS SQL Server 2000
开发与企业应用中,好几个版本SQL Server相互链接.分布式读取与存储,需要实现sp_addlinkedserver.SQL Server 2000, SQL Server 2008, SQL S ...
- 把sql server 2000的用户表的所有者改成dbo
怎么样把sql server 2000的用户表的所有者,改成dbo,而不是用户名. 推荐使用下面介绍的第二种方法,执行以下查询便可以了.sp_configure 'allow updates','1' ...
随机推荐
- notecase的下载与安装(全网最详细)(图文详解)
不多说,直接上干货! notecase是什么? 一个按照树状结构来组织文档内容的笔记管理程序 1.双击 2.aceept 3.选择安装所放置的目录路径 4.选择开启目录文件夹 我这里,保持默认 建议默 ...
- wordpress给文章添加缩略图
百度是个好东西,翻了半个小时的文章,终于把这个问题解决了. 一个问题的解决方法很多,但要找到一个自己理解的方法,缺比较难找,不管怎样,多动手,可能弄着弄着就会了. 教程开始: 1.先去后台管理安装Ea ...
- [Java初探08]__简单学习Java类和对象
前言 在前面的学习中,我们对面向对象的编程思想有了一个基本的了解,并且简单的了解了类和对象的定义.那么类和对象在Java语言中是如何表现的,这次,就从实际出发,学习一下一下类和对象在Java语言中的使 ...
- 高可用Hadoop平台-运行MapReduce程序
1.概述 最近有同学反应,如何在配置了HA的Hadoop平台运行MapReduce程序呢?对于刚步入Hadoop行业的同学,这个疑问却是会存在,其实仔细想想,如果你之前的语言功底不错的,应该会想到自动 ...
- Java中的简单工厂模式(转)
Java中的简单工厂模式 举两个例子以快速明白Java中的简单工厂模式: 女娲抟土造人话说:“天地开辟,未有人民,女娲抟土为人.”女娲需要用土造出一个个的人,但在女娲造出人之前,人的概念只存在于女娲的 ...
- MVC源码分析 - Action查找和过滤器的执行时机
接着上一篇, 在创建好Controller之后, 有一个 this.ExecuteCore()方法, 这部分是执行的. 那么里面具体做了些什么呢? //ControllerBaseprotected ...
- OSI七层模式简单通俗理解
OSI七层模式简单通俗理解 这个模型学了好多次,总是记不住.今天又看了一遍,发现用历史推演的角度去看问题会更有逻辑,更好记.本文不一定严谨,可能有错漏,主要是抛砖引玉,帮助记性不好的人.总体来说,OS ...
- jQuery加载部分视图(Partial Views)
本篇是演示使用jQuery加载部分视图(Partial View).如果你不想使用Razor的语法呈现部分视图,那此篇的方法是最理想的了.它可以Render至指定的tag上. 创建两个部分视图,一个为 ...
- 微信支付 统一下单 字段 body 为中文时 报【签名错误】解决方案(C# SDK)
方案一 如果你是从微信支付官网下载的 .NET C#[微信支付]API对应的SDK 调用示例 查看源码,会发现这个SDK中的 WxPayData 的类的 CalcHMACSHA256Hash 签名方法 ...
- Spring Boot配置Mybatis
在pom里加了mybatis的依赖后,在application.properties加上: mybatis.config-location=classpath:mybatis-config.xml m ...