设为首页 收藏本站
查看: 2128|回复: 0

[经验分享] SQL Server调优系列基础篇(常用运算符总结——三种物理连接方式剖析)

[复制链接]

尚未签到

发表于 2015-7-2 12:52:32 | 显示全部楼层 |阅读模式
  前言
  上一篇我们介绍了如何查看查询计划,本篇将介绍在我们查看的查询计划时的分析技巧,以及几种我们常用的运算符优化技巧,同样侧重基础知识的掌握。
  通过本篇可以了解我们平常所写的T-SQL语句,在SQL Server数据库系统中是如何分解执行的,数据结果如何通过各个运算符组织形成的。
  技术准备
  基于SQL Server2008R2版本,利用微软的一个更简洁的案例库(Northwind)进行解析。
  一、数据连接
  数据连接是我们在写T-SQL语句的时候最常用的,通过两个表之间关联获取想要的数据。
  SQL Server默认支持三种物理连接运算符:嵌套循环连接、合并连接以及哈希连接。三种连接各有用途,各有特点,不同的场景会数据库会为我们选择最优的连接方式。
  
  a、嵌套循环连接(nested loops join)
  嵌套循环连接是最简单也是最基础的连接方式。两张表通过关键字进行关联,然后通过双层循环依次进行两张表的行进行关联,然后通过关键字进行筛选。
  可以参照下图进行理解分析
DSC0000.png
  其实嵌套扫描是很简单的获取数据的方式,简单点就是两层循环过滤出结果值。
  我们可以通过如下代码加深理解



for each row R1 in the outer table
for each row R2 int the inner table
if R1 join with R2
return (R1,R2)
  举个列子



SELECT o.OrderID
FROM Customers C JOIN Orders O
ON C.CustomerID=O.CustomerID
WHERE C.City=N'London'
DSC0001.png
  以上这个图标就是嵌套循环连接的图标了。而且解释的很明确。
DSC0002.png
  这种方法的消耗就是外表和内表的乘积,其实就是我们所称呼的笛卡尔积。所以消耗的大小是随着两张表的数据量增大而增加的,尤其是内部表,因为它是多次重复扫描的,所以我们在实践中的采取的措施就是减少每个外表或者内表的行数来减少消耗。
  对于这种算法还有一种提高性能的方式,因为两张表是通过关键字进行关联的,所以在查询的时候对于底层的数据获取速度直接关乎着此算法的性能,这里优化的方式尽量使用两个表关键字为索引查询,提高查询速度。
  还有一点就是在嵌套循环连接中,在两张表关联的时候,对外表都是有筛选条件的,比如上面例子中【WHERE C.City=N'London'】就是对外表(Customers)的筛选,并且这里的City列在该表中存在索引,所以该语句的两个子查询都为索引查找(Index Seek)。
  但是,有些情况我们的查询条件不是索引所覆盖的,这时候,在嵌套循环连接下的子运算符就变成了索引扫描(Index scan)或者RID查找。
  举个例子



SELECT E1.EmployeeID,COUNT(*)
FROM Employees E1 JOIN Employees E2
ON E1.HireDate>E2.HireDate
GROUP BY E1.EmployeeID
  以上代码是从职工表中获取出每位职工入职前的人员数。我们看一下该查询的执行计划
DSC0003.png
  这里很显然两个表的关联通过的是HireDate列进行,而此列又不为索引项所覆盖,所以两张表的获取只能通过全表的聚集索引扫描进行,如果这两张表数据量特别大的话,无疑又是一个非常耗性能的查询。
DSC0004.png
  通过文本可以看出,该T-SQL的查询结果的获取是通过在嵌套循环运算符中,对两个表经过全表扫描之后形成的笛卡儿积进行过滤筛选的。这种方式其实不是一个最优的方式,因为我们获取的结果其实是可以先通过两个表过滤之后,再通过嵌套循环运算符获取结果,这样的话性能会好很多。
  我们尝试改一下这个语句



SELECT E1.EmployeeID,ECNT.CNT
FROM Employees E1 CROSS APPLY
(
SELECT COUNT(*) CNT
FROM Employees E2
WHERE E1.HireDate

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-82538-1-1.html 上篇帖子: SQL Server 服务器磁盘测试之SQLIO篇(一) 下篇帖子: 快速搞懂 SQL Server 的锁定和阻塞
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表