以前总结过一篇文章SQL SERVER中什么情况会导致索引查找变成索引扫描 介绍了几种索引查找(Index Seek)变成索引扫描(Index Scan)的情形。昨天写一篇文章的时候,也遇到了一个让人奇怪的执行计划。一时没有想明白为什么优化器会选择聚集索引扫描。案例详情请见SQL Server OPTION (OPTIMIZE FOR UNKNOWN) 测试总结 。  如下所示,测试环境为SQL Server 2014,数据库为AdventureWorks2014

CREATE PROCEDURE test (@pid int)

AS

SELECT * FROM [Sales].[SalesOrderDetail]

WHERE ProductID = @pid OPTION (OPTIMIZE FOR UNKNOWN);

[Sales].[SalesOrderDetail]的索引信息如下如下。其实这里优化器选择聚集索引扫描是因为Cost缘故。因为走非聚集索引查找(Index Seek)的话,Key Lookup的开销较大。整体开销比聚集索引扫描还大。我们可以测试验证一下

如下所示,我们新增一个SQL语句,强制其走索引查找(具体索引为IX_SalesOrderDetail_ProductID),然后执行对比查看执行计划的开销

ALTER PROCEDURE test (@pid int)

AS

SELECT * FROM [Sales].[SalesOrderDetail]

WHERE ProductID = @pid OPTION (OPTIMIZE FOR UNKNOWN);

SELECT * FROM [Sales].[SalesOrderDetail] WITH (INDEX =IX_SalesOrderDetail_ProductID)

WHERE ProductID = @pid;

GO

如下测试所示,两种实际执行计划的开销比为 22%  VS  78%。  所以优化器肯定会选开销小的执行计划。也就是说如果优化器发现当索引查找时,如果Key Lookup开销过大,那么优化器会选择聚集索引索引扫描。 这个案例就是一个活生生的案例。 也许有人会反问:不是Index Seek效率表Index Scan要高吗?你这有点不合逻辑,注意,这个特定条件下,虽然Index Seek变成 Index Scan,但是你注意一下上下文,索引变了, 从IX_SalesOrderDetail_ProductID变成了聚集索引PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID 。

总结: 任何现象背后都有一定的规律,有时候,只要你静下心来,仔细分析一下。就能一窥究竟。如果总是不问为什么,那么你总是不了解背后原理!也就永远止步不前!

Key Lookup开销过大导致聚集索引扫描的更多相关文章

  1. Sql Server 聚集索引扫描 Scan Direction的两种方式------FORWARD 和 BACKWARD

    最近发现一个分页查询存储过程中的的一个SQL语句,当聚集索引列的排序方式不同的时候,效率差别达到数十倍,让我感到非常吃惊 由此引发出来分页查询的情况下对大表做Clustered Scan的时候, 不同 ...

  2. Sql Server之旅——第四站 你必须知道的非聚集索引扫描

    非聚集索引,这个是大家都非常熟悉的一个东西,有时候我们由于业务原因,sql写的非常复杂,需要join很多张表,然后就泪流满面了...这时候就 有DBA或者资深的开发给你看这个猥琐的sql,通过执行计划 ...

  3. 陷阱~SQL全表扫描与聚集索引扫描

    SqlServer中在查询时,我们为了优化性能,通常会为where条件的字段建立索引,如果条件比较固定还会建立组合索引,接下来,我们来看一下索引与查询的相关知识及相关陷阱. SQL表自动为主键加聚集索 ...

  4. SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析

    在SQL SERVER的查询语句中使用OR是否会导致不走索引查找(Index Seek)或索引失效(堆表走全表扫描 (Table Scan).聚集索引表走聚集索引扫描(Clustered Index ...

  5. SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析 (转载)

    在SQL SERVER的查询语句中使用OR是否会导致不走索引查找(Index Seek)或索引失效(堆表走全表扫描 (Table Scan).聚集索引表走聚集索引扫描(Clustered Index ...

  6. SQLSERVER聚集索引与非聚集索引的再次研究(下)

    SQLSERVER聚集索引与非聚集索引的再次研究(下) 上篇主要说了聚集索引和简单介绍了一下非聚集索引,相信大家一定对聚集索引和非聚集索引开始有一点了解了. 这篇文章只是作为参考,里面的观点不一定正确 ...

  7. 索引深入浅出(4/10):非聚集索引的B树结构在聚集表

    一个表只能有一个聚集索引,数据行以此聚集索引的顺序进行存储,一个表却能有多个非聚集索引.我们已经讨论了聚集索引的结构,这篇我们会看下非聚集索引结构. 非聚集索引的逻辑呈现 简单来说,非聚集索引是表的子 ...

  8. MySQL索引的原理,B+树、聚集索引和二级索引的结构分析

    索引是一种用于快速查询行的数据结构,就像一本书的目录就是一个索引,如果想在一本书中找到某个主题,一般会先找到对应页码.在mysql中,存储引擎用类似的方法使用索引,先在索引中找到对应值,然后根据匹配的 ...

  9. SQLServer中重建聚集索引之后会影响到非聚集索引的索引碎片吗

    本文出处:http://www.cnblogs.com/wy123/p/7650215.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...

随机推荐

  1. vscode mysql v0.3插件 连接不了

    环境: centos7.6  x64 python 3.6 插件mysql v0.3 解决办法:回滚插件版本v0.2.3 使用方法注意: https://www.cnblogs.com/-admin- ...

  2. 经典中的品味:第二章 C++基本的对象,类型和值(上)

    摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆木匠 希望转载,保留摘要,谢谢! 自律,是以积极而主动的态度,去解决人生的痛苦~ 上一章,我们大谈了Hel ...

  3. python args kwargs 传递参数的区别

    先来看个例子: def foo(*args, **kwargs): print 'args = ', args print 'kwargs = ', kwargs print '----------- ...

  4. SpringBoot2.0应用(五):SpringBoot2.0整合MyBatis

    如何整合MyBatis 1.pom依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <ar ...

  5. 【原创】STM32下波特率计算详解

    波特率的计算 STM32下的波特率和串口外设时钟息息相关,USART 1的时钟来源于APB2,USART 2-5的时钟来源于APB1.在STM32中,有个波特率寄存器USART_BRR,如下:     ...

  6. 字符串不相同出现相同HashCode(算法)

    转自:https://blog.csdn.net/fly_grass_fish/article/details/81742794 在Java中有HashCode的说法,以前以为HashCode是唯一的 ...

  7. springboot情操陶冶-SpringApplication(一)

    SpringApplication是所有springboot的入口类,分析此类有助于我们了解springboot的工作机制.本文以2.0.3.REALEASE版本作分析 SpringApplicati ...

  8. C# 通过java生成的RSA公钥加密和解密

    最近工作需要将对方公司生成的RSA加密公钥进行明文加密和解密,发现了几点贴出来做个笔记. RSA单次加密是有长度限制!微软封装的加密方法如果出现长度超出指定范围的话报错是直接报“该项不适于在指定状态下 ...

  9. Linux下的java虚拟机性能监控与故障处理命令

    java包中提供了很多监控JVM的工具类,作为java程序员必须得掌握常用的几个工具,下面是几个常用的JVM性能监控与故障处理工具的介绍与使用. 1.jstack 该命令用于生成当前时刻虚拟机的线程快 ...

  10. IPv6笔记

    单播地址包含的几种类型:1.AGUA地址:2000::到3FFF:FFFF:FFFF:FFFF:FFFF..... 一个接口可以拥有若干个AGUA地址2.Link-Local 地址:FE80::/10 ...