计划缓存

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介:

今天我想进一步谈下SQL Server里的计划缓存和它的副作用。我们都知道,每个提交到SQL Server的逻辑查询,会编译为物理执行计划。这个执行计划然后会缓存为所谓的计划缓存,用于后期重用。现在我们首先来谈下即席SQL语句和它的负作用,还有它们带来的性能问题。

即席SQL语句(Adhoc SQL Statements)

每次当你提交一个即席SQL语句到SQL Server,对于每个特定查询,都会生成一个执行计划。“特定查询”是什么意思?答案很简单:SQL Server对每个完整的SQL语句(包括你的参数值)生成一个哈希值,并使用这个哈希值作为计划缓存的查找值。如果使用这个哈希值找到一个执行计划,计划就会重用,否则在计划缓存里会编译一个新的执行计划。假设你提交下列3个查询到SQL Server:

复制代码
SELECT * FROM Sales.SalesOrderHeader
WHERE CustomerID = 11000
GO

SELECT * FROM Sales.SalesOrderHeader
WHERE CustomerID = 30052
GO

SELECT * FROM Sales.SalesOrderHeader
WHERE CustomerID = 11223
GO
复制代码

对于这3个查询,SQL Server编译3个不同的执行计划,因为你提供了硬编码的参数值。因此3个查询间会计算不同的的哈希值,不会找到已缓存的计划。作为副作用,在计划缓存里,现在你有近3个近乎一样的查询有3个不同的计划。这个特定问题被称为计划缓存污染

你刚用不同的执行计划污染了你的计划缓存,这很难重用(因为硬编码的参数值),而且你在浪费可以被SQL Server里其它组件使用的有用内存。缓存的目的应该提高重用数,但使用即席SQL语句就做不到。

计划稳定性

假设你为你的SQL语句使用参数值,或者你甚至使用存储过程。在这个情况下,SQL Server非常容易重用缓存的执行计划。但即使重用缓存的执行计划,你回引入性能问题。例如SQL Server为一个查询编译了一个执行计划,它回进行书签查找,因为非聚集索引没有覆盖你的查询:

 

我们提过,书签查找只有在从表里获取一些数据才有意义。如果你越过了临界点,使用全表扫描或聚集索引扫描更高效。但如果SQL Server冲了缓存的执行计划,这个选项就不会考虑太多——SQL Server会盲目重用你的计划——这时你的性能就会很差!可以看下面的例子:

这里SQL盲目重用了有书签查找的缓存计划。你会看到估计和实际行数有很大差别!SQL Server在假设从查询里只返回一条记录来编译和缓存计划。但实际上从SQL Server我们拿回1499条记录。你看到的执行计划,是假设只有一条记录返回的情况下优化——考虑下这个情况。

这里潜在的根源是你的计划不稳定。基于估计行数,你得到有书签查找的缓存计划,如果你越过临界点,会是表/聚集索引扫描。这是我们经常碰到的常见SQL Server性能问题。

你如何解决这个问题?简单:通过覆盖非聚集索引来避免书签查找。使用这个方法你会获得计划稳定性,不管你的输入参数,你会得到同样的性能。

小结

今天你学到了SQL Server里,计划缓存的双刃剑:在一方面,计划缓存非常强大,因为你可以重用计划缓存避免编译资源占用。在另一方面,他非常危险,使用定型的执行计划,你的计划不再稳定,这就意味着你不能再保证性能。



本文转自Woodytu博客园博客,原文链接:http://www.cnblogs.com/woodytu/p/6654771.html,如需转载请自行联系原作者

相关实践学习
使用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
相关文章
|
3月前
|
缓存
你了解缓存吗?
你了解缓存吗?
你了解缓存吗?
|
10月前
|
存储 缓存 API
缓存 #23
缓存 #23
30 0
|
存储 缓存 前端开发
缓存的认识
缓存是架构设计中一个重要的手段。缓存的主要特点是技术比较简单,同时对性能提升的效果又很显著,所以缓存在很多业务场景中被使用到。
107 0
|
缓存 开发框架 NoSQL
7.4缓存
缓存是一个用来保存数据的区域,从缓存中读取数据要比从数据源读取数据的速度快很多。如果可以从缓存中获取要获取的数据则称之为“缓存命中”,多次请求命中的请求占全部请求的百分比叫做“命中率”,如果数据源中的数据保存到了缓存后,发生了变化则称之为“缓存数据不一致”
|
存储 缓存 NoSQL
聊聊缓存
拿破仑说:胜利属于坚持到最后的人。 而正巧,咱们今天就是要聊一个,关于怎么让系统在狂轰乱炸甚至泰山压顶的情况下,都屹立不倒并坚持到最后的话题:缓存。
141 0
|
存储 缓存 算法
聊聊缓存那些事
说到缓存,作为技术同学想必大家都不会陌生,平常工作中或多或少也用到过。但是要结构化的说清楚缓存到底是什么,怎么用,用了有问题怎么解,也不是一件简单的事。所以这篇文章也是站在服务端研发的视角,对自己过去经验的一些总结,希望对大家有哪怕一丁点的帮助,也就值得了。 本篇文章计划分为两个章节来写: ● 缓存基础篇:讲一下缓存的基本原理、特性等。 ● 缓存进阶篇:讲一下缓存的实战场景,疑难问题的解决方案等。
132 0
|
存储 缓存 运维
常用缓存技巧
在项目中,大家经常会遇到处理高并发的情况,缓存是应对高并发的有效手段之一。这篇文章简单介绍一下常用的缓存手段。
|
存储 缓存 JSON
缓存的注意点
设计缓存的考虑
|
缓存 中间件
你真的懂缓存使用么?
在业务开发中我们经常会使用缓存来减少服务的响应rt,提升服务性能。除了先读缓存-miss后读DB-再写缓存的套路外,其实还有其他很多套路,本文将从使用模式、对数据一致性要求等方面为大家解释其中的细节。一、缓存模式1.1 Cache-aside该模式就是上文中提到的,也是大家用的最多的模式1.业务先读缓存,如果命中直接返回      2如果未命中,业务加载db数据放入缓存,然后返回1.2 Read-
385 0
|
消息中间件 缓存 NoSQL
缓存
缓存
461 0
缓存