第六章——根据执行计划优化性能(1)——理解哈希、合并、嵌套循环连接策略

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介: 原文: 第六章——根据执行计划优化性能(1)——理解哈希、合并、嵌套循环连接策略 前言: 本系列文章包括: 1、 理解Hash、Merge、Nested Loop关联策略。
原文: 第六章——根据执行计划优化性能(1)——理解哈希、合并、嵌套循环连接策略

前言:

本系列文章包括:

1、 理解Hash、Merge、Nested Loop关联策略。

2、 在执行计划中发现并解决表/索引扫描。

3、 介绍并在执行计划中发现键查找并解决它们。

 

对于性能优化,需要集中处理以下的问题:

1、 为你的环境创建性能基线。

2、 监控现在的性能并发现瓶颈。

3、 解决瓶颈以便得到更好的性能。

 

一个预估执行计划是描述查询将会如何执行的一个蓝图,而一个实际执行计划就是一个查询执行时实际发生的镜像。通过对比两个执行计划,可以发现查询是否真的按照预估执行计划来执行。

在执行计划中,有一些非常重要的操作符需要清楚:

1、           Join策略:SQLServer有3种策略——哈希、合并、嵌套循环。每种策略都有其优缺点,本章将讲述这部分。

2、           扫描和查找是SQLServer用于读取数据的两种方式,这两种方式在性能优化中是核心概念。将会在下一篇中讲述。

3、           键查找有时候会成为主要的性能问题。因为存储引起必须从非聚集索引中跳到聚集索引,一边找到非聚集索引中的非键值列的值。这样的行为通常很耗时间。

 

理解哈希、合并、嵌套循环连接策略

SQLServer提供了3中JOIN的策略,它们没有绝对的好和坏之分。

 

1、 哈希(Hash Join):SQLServer选择哈希关联作为物理操作符,一边对于大容量数据,且未排序或者没有索引时进行查询。两个进程关联起来进行哈希关联,它们为【建立】和【探测】,在【建立】进程中,会从建立输入(即join的左表中,但是可能这个左表会在优化过程中交换位置,使得不一定就是实际上的左表。)读取所有行,然后在内存中创建一个符合关联条件的哈希表。在【探测】进程中,会从探测表(输入的右表)中读取所有的行,并根据关联条件,与之前创建的内存哈希表匹配。

2、 合并(Merge Join):如果关联表中已经排序,SQLServer会选择合并关联。合并关联要求关联条件中最少有一个是已经被排序了的。如果数据量不大的时候,这比哈希关联更加有效,它并不是重负荷关联的方式。

3、 嵌套循环(Nested Loop):在最少两个结果集中,使用嵌套循环会比较有效,这两个结果集中,作为外部表的集合要小,而内部循环结果集具有有效的索引。这种方式不适用于大结果集。

准备工作:

下面将创建两个表,然后看看各种关联方式的执行计划:

USE AdventureWorks
GO
IF OBJECT_ID('SalesOrdHeaderDemo') IS NOT NULL 
    BEGIN
        DROP TABLE SalesOrdHeaderDemo
    END
GO

IF OBJECT_ID('SalesOrdDetailDemo') IS NOT NULL 
    BEGIN
        DROP TABLE SalesOrdDetailDemo
    END
GO

SELECT  *
INTO    SalesOrdHeaderDemo
FROM    Sales.SalesOrderHeader
GO

SELECT  *
INTO    SalesOrdDetailDemo
FROM    Sales.SalesOrderDetail
GO


步骤:

1、 执行一下查询,并开启执行计划(Ctrl+M):

SELECT  sh.*
FROM    SalesOrdDetailDemo AS sd
        INNER JOIN SalesOrdHeaderDemo AS sh ON sh.salesorderID = sd.salesorderid
GO


2、 然后从执行计划截图中可以看到使用了哈希连接:


3、 现在先创建唯一的聚集索引在两个表中:

CREATE UNIQUE CLUSTERED INDEX idx_salesorderheaderdemo_SalesOrderID ON salesordheaderdemo(SalesOrderID)

GO

CREATE UNIQUE CLUSTERED INDEX idx_SalesDetail_SalesOrderID ON SalesOrdDetailDemo(SalesOrderID,SalesOrderDetailID)

GO


4、 再次执行步骤1的语句:

5、 截图是第二次执行的执行计划,可以发现变成了合并连接,并且表扫描变成了聚集索引扫描:


6、 现在来看看嵌套循环关联,在上面的查询中添加where条件来限定查询的结果集:

SELECT  sh.*
FROM    SalesOrdDetailDemo AS sd
        INNER JOIN SalesOrdHeaderDemo AS sh ON sh.salesorderID = sd.salesorderid
WHERE   sh.salesorderid = 43659
GO



7、 从执行结果中看到现在关联变成了嵌套循环: 

 

分析:

        前面已经提到,哈希关联工作在大数据量且关联字段没有排序的关联中。所以在步骤1中,由于没有索引或者预先排序,数据的关联会使用哈希关联。

        在步骤3中,创建了一个唯一的聚集索引,所以表已经通过聚集索引排序了,此时优化器会选择合并关联。

        在步骤6中,由于使用了where条件限制数据集的大小,同时由于已经排序,所以使用了嵌套循环关联。

        每一种关联方法都有其优缺点,视乎如何优化而已。有时候哈希关联有其非常重要的作用,但是如果可以,强烈建议每个表都应该有一个唯一的聚集索引,一边使用合并关联,如果不可以,千万别尝试使用OPTION提示符来把关联改成合并或者嵌套循环,这可能会降低性能。而嵌套循环仅在小结果集的时候运行的最好。

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
23天前
|
缓存 关系型数据库 MySQL
MySQL查询优化:提速查询效率的13大秘籍(合理使用索引合并、优化配置参数、使用分区优化性能、避免不必要的排序和group by操作)(下)
MySQL查询优化:提速查询效率的13大秘籍(合理使用索引合并、优化配置参数、使用分区优化性能、避免不必要的排序和group by操作)(下)
|
23天前
|
缓存 关系型数据库 MySQL
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
|
23天前
|
存储 关系型数据库 MySQL
MySQL数据库性能大揭秘:表设计优化的高效策略(优化数据类型、增加冗余字段、拆分表以及使用非空约束)
MySQL数据库性能大揭秘:表设计优化的高效策略(优化数据类型、增加冗余字段、拆分表以及使用非空约束)
|
18天前
|
存储 关系型数据库 MySQL
mysql索引优化,更好的创建和使用索引
mysql索引优化,更好的创建和使用索引
|
4月前
|
SQL 分布式计算 算法
当两个表进行Join操作时,如果它们的数据不符合MapJoin规范,您可以尝试以下优化方案
当两个表进行Join操作时,如果它们的数据不符合MapJoin规范,您可以尝试以下优化方案
46 4
|
5月前
|
SQL 关系型数据库 MySQL
sql处理重复的列,更好理清分组和分区
sql处理重复的列,更好理清分组和分区
46 0
|
8月前
|
数据库 索引
数据库查询条件优化方案
数据库查询条件优化方案
|
9月前
|
关系型数据库 MySQL 数据库
MySQL数据库索引的原理和优化策略
MySQL数据库索引的原理和优化策略
|
SQL 移动开发 BI
【SQL开发实战技巧】系列(二十三):数仓报表场景☞ 如何对数据排列组合去重以及通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高
怎样对数据组合重新排列并去重的问题、通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。本篇文章主要介绍的两个方面,第一个方面曾经有好几个网友和同事问我,第二个问题真的是很多同行的通病,认为分析函数是万金油,一股脑用。
【SQL开发实战技巧】系列(二十三):数仓报表场景☞ 如何对数据排列组合去重以及通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高
|
SQL 关系型数据库 数据库
MySQL优化系列(二)--查找优化(1)(非索引设计)
MySQL优化系列(二)--查找优化(1)(非索引设计) 接下来这篇是查询优化,用户80%的操作基本都在查询,我们有什么理由不去优化他呢??所以这篇博客将会讲解大量的查询优化(索引以及库表结构优化等高级用法后面文章再讲),先讲单表查优化,再讲多表查优化。
1763 0