表关联:Hash、Nested Loops、Merge。这是实际算法,不是T-SQL中的inner/left/right/full/cross join。优化器会把这些T-SQL写法转换成上面的3种算法。

通过这3种算法,可以推出其他操作符的行为。

1.Hash Match Join

Hashing(散列法)和Hash Table。

Hashing:是编码技术,把数据转换成符号格式,以便有效的支持数据查询。如SQL Server会把一行数据转换成一个能标识这行数据内容的唯一值,并存放到一个表中,这个表就是Hash Table,也就是哈希表,这种技术类似加密,当需要原始数据时,也能解密出来。

Hash Table:实际上是一个数据结构,通过散列法的处理,把数据存放到表中,如SQL Server从一个实体表中查询数据,并把数据转成哈希值,存放到一个哈希表中,这个表则存放在tempdb中。

当SQL Server 把两个数据放入临时的哈希表中,然后用这个结构对比数据,并返回匹配的数据时,就会出现Hash Match操作符。

select e.JobTitle,a.City,p.LastName+','+ p.FirstName as EmployeeName
from HumanResources.Employee as e
join Person.BusinessEntityAddress as bea
on e.BusinessEntityID=bea.BusinessEntityID
join Person.Address a
on bea.AddressID=a.AddressID
join Person.Person as p
on e.BusinessEntityID =p.BusinessEntityID

  

这个Hash Match Join操作把Index Scan和Nested Loops合并,然后输出结果集,这个操作符是开销比较大的操作符,在性能优化中也应该纳入检查范畴。看看tooltips

当SQL Server必须关联两个大数据集时,会把两个数据集中较小那个集合的数据进行散列处理,把哈希值存入tempdb的哈希表上,然后较大的那个数据集,会一行一行的与哈希表匹配,以便实现‘关联’逻辑,由于较小的表已经被转换成哈希表,所以它的体积会变得更小,在对比时使用哈希值相对较快。所以如果哈希表比较小,处理速度将会更快。如果两表都很大,对比于其他类型的关联算法,Hash Match Join会非常低效。同时,由于Hash表中存放在tempdb中,所以查询中的Hash Join将会给tempdb带来很大的负载压力。

当看到Hash Match时,应该检查一下是否存在下面的问题:

丢失索引或者无效索引

缺少Where条件

where条件中存在非SARG操作,如对筛选列进行标量函数、隐式类型转换等,

以上会导致优化器不使用上面已由的索引。

Hash Match暗示着你可能需要检查查询是否有改写可能,是否可以加索引,使其关联时更加有效,如果没有可能,Hash Match Join也不失为一个高效的算法。

2.Nested Loops Join

上面的执行计划右边第一个是Nested Loops操作符。表Employee和表BusinessEntityAddress上分别存在聚集索引扫描和聚集索引查找,连个操作通过箭头汇总到Nested Loops操作符中

Nested Loops Join涉及两个数据集,一个叫做inner set,一个叫做outer set,位于上方的是outer set,下方的为inner set。这种算法把inner set的数据集与outer set一一匹配,知道inner set的数据集全部扫描完毕为止。如果两个数据集都很小,或者inner set数据很小,这种算法可算是最佳关联算法。

3.Merge Join

它的特点:关联的数据已经排序。这种算法把两个数据集合并到一起,由于已经预先排序,所以数据合并后已是有序的。然后会和匹配值匹配,排序的数据可以很快地标识数据,如1,2,3这样的数据,如果匹配到数据2已经找到,就不需要在往后查找了。

对于已经排序的数据集,这种算法是其中一种最高效的算法,但是很多时候数据集都是无序的,所以这种算法会引入一个排序操作符来协助工作,这个操作符会降低预期的

 select c.CustomerID from Sales.SalesOrderDetail od
join Sales.SalesOrderHeader oh on od.SalesOrderID=oh.SalesOrderID
join Sales.Customer c on oh.CurrencyRateID=c.CustomerID

  

由于没有Where条件,SalesOrderHeader和Customer会进行相应的扫描操作。得到的数据集会通过Merge Join关联,当关联列已排序时,优化器会考虑用这种算法。关联使用了CustomerID作为两表关联关系,而这个列在两表中均有索引,也就是预排序。

这种算法对预排序的关联列非常高效。反之,如果关联列没有预排序,优化器又选择了这种算法,就会出现以下两种情况:

1.优化器预先排序关联列,然后在进行Merge Join

2. 使用较为低效的Hash Match关联

四.筛选数据

 select e.JobTitle,a.City,p.LastName+', '+p.FirstName as EmployeeName
from HumanResources.Employee as e
join Person.BusinessEntityAddress as bea on e.BusinessEntityID=bea.BusinessEntityID
join Person.Address a on bea.AddressID=a.AddressID
join Person.Person as p on e.BusinessEntityID=p.BusinessEntityID
where e.[JobTitle]='Production Technicaian - WC20'

  

右上角的聚集索引扫描,WHERE条件使用PK_Employee_BusinesEntityID把数据集控制到了22行,由于数据量很小,优化器决定使用Nested Loops算法关联两表,产生数据集

聚集索引扫面的影响函数:

嵌套循环后的影响行数:

可以看到数据量还是很少,下一步优化器会用这个结果集和Address上通过聚集索引查找获得的数据再次进行Nested Loops。由于查询中添加了where子句,所以把数据控制到了很小的程度。把where条件去掉,再看之心计划,从中可以看到添加条件的重要性。

使用SET STATISTICS TIME ON 和SET STATISTICS IO ON查询。然后分别执行,查看数值,当然,前提是返回结果是一致的,不一致的数据没什么可比性。还有,就是把两个查询放到一个查询界面,然后打开实际执行计划,运行查询,再从执行计划中对比两者的开销,通常来说,百分比越低,开销越小,理论上性能也就越好。

SQL Server表关联的更多相关文章

  1. SQL Server表分区【转】

    转自:http://www.cnblogs.com/knowledgesea/p/3696912.html SQL Server表分区   什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在 ...

  2. SQL Server表分区详解

    原文:SQL Server表分区详解 什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在一个文件里. 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆 ...

  3. SQL Server表分区-水平分区

    SQL Server表分区,sql server水平分区 转自:http://www.cnblogs.com/knowledgesea/p/3696912.html  根据时间的,直接上T-SQL代码 ...

  4. 在一个SQL Server表中的多个列找出最大值

    在一个SQL Server表中一行的多个列找出最大值 有时候我们需要从多个相同的列里(这些列的数据类型相同)找出最大的那个值,并显示 这里给出一个例子 IF (OBJECT_ID('tempdb..# ...

  5. SQL Server表分区的NULL值问题

    SQL Server表分区的NULL值问题 SQL Server表分区只支持range分区这一种类型,但是本人觉得已经够用了 虽然MySQL支持四种分区类型:RANGE分区.LIST分区.HASH分区 ...

  6. SQL Server 表变量和临时表的区别

    SQL Server 表变量和临时表的区别 一.表变量 表变量在SQL Server 2000中首次被引入.表变量的具体定义包括列定义,列名,数据类型和约束.而在表变量中可以使用的约束包括主键约束,唯 ...

  7. [转载]在SQL Server 中,如何实现DBF文件和SQL Server表之间的导入或者导出?

    原来使用SQL Server 2000数据库,通过DTS工具很方便地在SQL Server和DBF文件之间进行数据的导入和导出,现在安装了SQL Server2005之后,发现其提供的“SQL Ser ...

  8. SQL server 表中如何创建索引?

    SQL server 表中如何创建索引?看个示例,你就会了 use master goif db_id(N'zhangxu')is not nulldrop database zhangxugocre ...

  9. 图解SQL多表关联查询

      图解SQL多表关联查询     网上看了篇文章关于多表连接的,感觉很好,记录下来,以便日后自己学习  内连接     左连接     右连接       全外连接   1. 查两表关联列相等的数据 ...

随机推荐

  1. CF1096E The Top Scorer

    题目地址:洛谷CF1096E 本场AC数最少 (最难) 的题目 题目大意:给出三个数p , s,r,表示有p人,每个人都有一个非负得分,所有人的得分和为s,Hasan的得分至少为r,求Hasan是第一 ...

  2. Python3-lamba表达式、zip函数

    lambda表达式 学习条件运算时,对于简单的 if else 语句,可以使用三元运算来表示,即: # 普通条件语句 == : name = 'wupeiqi' else: name = 'alex' ...

  3. Jenkins远程构建

    首先在Jenkins上配置Job: 按照图片形式,仅需往对应的url发送请求即可 Shell如下: import json import urllib.parse,http.client def po ...

  4. k64 datasheet学习笔记35---Analog-to-Digital Converter (ADC)

    0.前言 本文主要介绍K64的ADC部分的特性,内部架构,信号描述及操作接口等 1.简介 1.1.ADC模块特性 线性逐次逼近算法,达16bit分辨率 达到4对差分和24个单端模拟量输入 输出模式 差 ...

  5. 利用crash 分析软死锁问题【转】

    转自:https://blog.csdn.net/divlee130/article/details/47806551 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog. ...

  6. 如何在Delphi 中使用 DevExpressVCL的 CxGrid与CxTreeList,编辑某列后计算另一列的值

    如何在Delphi 中使用 DevExpressVCL的 CxGrid与CxTreeList,编辑某列后计算另一列的值:比如 输入 单价,数量,计算金额. 参考: 1.  输入 单价,数量,计算金额 ...

  7. Windows PowerShell 入門(3)-スクリプト編

    これまでの記事 Windows PowerShell 入門(1)-基本操作編 Windows PowerShell 入門(2)-基本操作編 2 対象読者 Windows PowerShellでコマンド ...

  8. 快速安装freeswitch

    前不久在Centos 6.4上安装了一台Freeswitch,测试已经OK.为了测试FS 的集群效果,从新在安装一台FS,快速安装的过程如下: 方案一:快速安装前提:不用重新下载Freeswitch. ...

  9. python学习第38天

    mysql的存储引擎(innodb,myisam)mysql支持的数据类型约束表的创建\删除\修改\查看表结构表与表之间的关系

  10. 46)django-发送邮件

    django已封装好了邮件发送功能,可以直接调用发送模块 1. 配置相关参数 如果用的是 阿里云的企业邮箱,则类似于下面: 在 settings.py 的最后面加上类似这些 EMAIL_BACKEND ...