查询优化器内核剖析第三篇:查询的执行与计划的缓存 & Hint提示

简介:
查询优化器内核剖析第三篇:查询的执行与计划的缓存 & Hint提示
 
本篇议题如下:
查询的执行与计划的缓存
Hint提示
 
首先看到第一个议题
 
查询的执行与计划的缓存
 
     一旦查询被优化之后,存储引擎就使用选中的执行计划将结果返回,而被使用的这个执行计划就会被保存在内存中一个被称之为“计划缓存”的地方,从而使得这个执行计划可以被重用,从而节省CPU等资源。
 
    尽管我们可以把执行计划缓存起来,便于重用,但是在某些情况,对于某些查询而言,计划重用并不是很好的选择。这是为什么?这主要取决于表中数据的分布情况和查询中所使用的参数,其实这种情况也被称为“参数嗅探(Parameter Sniffing,翻译过来还是很别扭的)”。
这里,我们就简单的说一下(详细的后续文章会慢慢的介绍)。例如,假设有这样一个查询语句,如下图所示:
 
20120321111321.png
 
    执行如下:
20120321111330.png
 
 
    这个时候,存储过程运行,产生了一个执行计划,并且被缓存起来了。
    之后,又要运行这个查询,但是传入的参数不同,如下:
20120321111340.png
 
    这个时候,这个查询可以使用之前创建的执行计划,但是这个时候也很有可能之前的执行计划对与参数870不是最优化的。因为之前在生成的执行计划的时候,查询优化器是通过传入的897创建的执行计划。
 
    试想:如果在表中的数据,有很多的ProductId的值都为897,即使我们在ProductId上面建立了索引,但是还有可能查询优化器决定在执行计划会采用扫描整表来获取数据。而对于参数值为870的时候,在表中的存在相同的ProductId为870的数据很少,这个时候,如果采用索引查找,可能会更快,那么就说明之前的执行计划中的整表扫描不适合了!
 
    当然,这里只是简要的说明了一下,大家可能不是非常的明白,没关系,只要知道有这么个情况就行了,我们在后面会详细剖析。
有时候,即使执行计划已经在计划缓存中存在了,但是有可能随着一些元数据的改变(修改表的结构,移除索引等操作)会导致执行计划失效,或者不是比较优化的,或者甚至从计划缓存中移除。当SQL Server存在内存压力的时候,一些执行计划也会被移除,释放内存。
 
Hint提示
 
    在大部分情况下,查询优化器都会选择比较高效的执行计划,
 
    但是,在有些情况下,查询优化器选择的执行计划没有达到预期的效果,或者说,查询优化器做出了错误的选择。造成这个问题的原因是我们没有为SQL Server提供准确的信息,例如数据库的统计信息过期了。
 
    同时,在有些情况下,我们根据我们的经验和分析判断,发现SQL Server选择的执行计划不是我们想要的。
 
    当遇到上面的情况的时候,我们就可以给查询优化器一些提示信息,去告诉它该如何产生执行计划,也就是我们自动的去干预查询优化器的默认行为。
 
    为了让大家有一个感性的认识,我这里举一个例子,对于下面的查询:
 
20120321111535.png
 
 
    我们通过查询它的执行计划,如下图所示:
 
20120321111552.png
 
    我们发现,这个查询计划不够高效,于是我们改写查询语句,如下:
 
20120321111736.png
    在语句中,我们强制的使得查询优化器选择我们要的连接方式,
 20120321111744.png
    执行计划如下:
 
 
20120321111846.png
 
 
    大家如果对这里的知识不明白,没有关系,这里的例子只是让大家感受一下。
 
    注意:一般情况下,我们没有必要去干扰查询优化器的工作,因为它会已经足够的“智能”去选择更好的执行计划,除非我们非常有信心,并且证明我们用一些Hint会提升性能,这个时候,我们可以加入Hint。事实是,我们加入的Hint都是会产生很多的问题。
 
    本篇就暂时到这里!后一篇文章就稍微详细一点的来看看与执行计划相关的一些话题。
 
   系列文章索引:       
 
         查询优化器内核剖析第一篇      
查询优化器内核剖析第二篇:产生候选执行计划&执行计划成本估算
查询优化器内核剖析第三篇:查询的执行与计划的缓存 & Hint提示























本文转自yanyangtian51CTO博客,原文链接: http://blog.51cto.com/yanyangtian/813238 ,如需转载请自行联系原作者


相关文章
|
2月前
|
存储 缓存 索引
从底层数据结构和CPU缓存两方面剖析LinkedList的查询效率为什么比ArrayList低
本文详细对比了ArrayList和LinkedList的查询效率,从底层数据结构和CPU缓存两个方面进行分析。ArrayList基于动态数组,支持随机访问,查询时间复杂度为O(1),且CPU缓存对其友好;而LinkedList基于双向链表,需要逐个节点遍历,查询时间复杂度为O(n),且CPU缓存对其帮助不大。文章还探讨了CPU缓存对数组增删操作的影响,指出缓存主要作用于读取而非修改。通过这些分析,加深了对这两种数据结构的理解。
47 2
|
4月前
|
存储 缓存 关系型数据库
查询缓存效果
【8月更文挑战第14天】
38 2
|
4月前
|
存储 缓存 NoSQL
微服务复杂查询之缓存策略
微服务复杂查询之缓存策略
|
4月前
|
缓存 关系型数据库 MySQL
【缓存大对决】Memcached VS MySQL查询缓存,谁才是真正的性能之王?
【8月更文挑战第24天】在现代Web应用中,缓存技术对于提升性能与响应速度至关重要。本文对比分析了Memcached与MySQL查询缓存这两种常用方案。Memcached是一款高性能分布式内存对象缓存系统,支持跨服务器共享缓存,具备灵活性与容错性,但受限于内存大小且不支持数据持久化。MySQL查询缓存内置在MySQL服务器中,简化了缓存管理,特别适用于重复查询,但功能较为单一且扩展性有限。两者各有所长,实际应用中可根据需求单独或结合使用,实现最佳性能优化。
144 0
|
4月前
|
缓存 Java 数据库连接
Hibernate 中的查询缓存是什么?
【8月更文挑战第21天】
43 0
|
4月前
|
缓存 数据库 SQL
查询缓存 面试准备
【8月更文挑战第13天】
33 0
|
6月前
|
缓存 NoSQL Java
Redis系列学习文章分享---第四篇(Redis快速入门之Java客户端--商户查询缓存+更新+双写一致+穿透+雪崩+击穿+工具封装)
Redis系列学习文章分享---第四篇(Redis快速入门之Java客户端--商户查询缓存+更新+双写一致+穿透+雪崩+击穿+工具封装)
74 0
|
2天前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
114 85
|
2月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
79 6
|
1月前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题