SqlServer 中如何查看某一个Sql语句是复用了执行计划,还是重新生成了执行计划

我们知道SqlServer的查询优化器会将所执行的Sql语句的执行计划作缓存,如果后续查询可以复用缓存中的执行计划,那么SqlServer就会为后续查询复用执行计划而不是重新生成一个新的执行计划,因为复用执行计划的性能比生成执行计划的性能要高很多,所以SqlServer的这一特性可以大大提高Sql语句的执行效率。特别是对于存储过程,因为存储过程的执行计划是在存储过程第一次执行的时候生成的,存储过程的执行计划生成后就会被缓存到SqlServer的执行计划列表中,如果以后存储过程再被执行,那么存储过程的执行计划就可以被复用(除非查询优化器认为该存储过程的执行计划已经过时,否则一般都会被复用),性能大大提升。

那么现在我们怎么才能知道执行的Sql语句是复用的SqlServer缓存的执行计划,还是重新生成的执行计划呢?

我们可以通过Sql Server Profiler这个工具来看到执行计划是否被查询优化器复用。

首先打开Sql Profiler,新建一个跟踪

然后在 事件选择 面板上选中 显示所有事件

然后在事件列表里面,选中 Stored Procedures 类别下的 SP:CacheHit SP:CacheMiss 事件,如果Sql Profiler中出现了SP:CacheHit事件表示SqlServer为查询语句复用了缓存中的执行计划,如果出现了SP:CacheMiss 事件表示SqlServer为查询语句重新生成了执行计划

接着我们随便执行一个Sql语句如下

select * from [dbo].[T_People]

从下图中我们发现在Sql Profiler出现了SP:CacheMiss 事件,因为我们是在SqlServer中第一次执行该查询,所以SqlServer的缓存列表中并没有该查询语句的执行计划,所以SqlServer为该查询语句重新生成了执行计划。

接着我们再次执行上面的查询语句,这一次Sql Profiler出现了SP:CacheHit  事件,说明SqlServer这次为查询语句复用了缓存中的执行计划,并没有重新生成执行计划。

使用如下语句可以清除SqlServer目前所有缓存的执行计划,为所有Sql语句重新生成执行计划,切记不要在客户生产环境上执行如下语句!

DBCC FREEPROCCACHE

所以通过Sql Profiler我们可以跟踪到执行的每条Sql语句是否重新生成了执行计划,从而知道对查询性能的影响是什么。对于SqlServer是否会为查询语句复用执行计划也是一个非常复杂的问题,诸如查询条件参数化这样的手段都可以增加执行计划的复用性,有兴趣的朋友可以参考下面三篇文章做详细了解,这三篇文章都详细地解释了SqlServer执行计划的复用机制,写的非常全面。

谈一谈SQL Server中的执行计划缓存(上)
谈一谈SQL Server中的执行计划缓存(下)
执行计划的重用

时间: 2024-11-06 21:26:15

SqlServer 中如何查看某一个Sql语句是复用了执行计划,还是重新生成了执行计划的相关文章

SQL Server中存储过程 比 直接运行SQL语句慢的原因

问题是存储过程的Parameter sniffing 在很多的资料中都描述说SQLSERVER的存储过程较普通的SQL语句有以下优点: 1. 存储过程只在创造时进行编译即可,以后每次执行存储过程都不需再重新编译,而我们通常使用的SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度. 2. 经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用SP来封装数据库操作.当对数据库进行复杂操作时(如对多个表进行 Update,Insert,Query,Delete时),可将此复杂操作用

SQL Server中存储过程比直接运行SQL语句慢的原因

原文:SQL Server中存储过程比直接运行SQL语句慢的原因 在很多的资料中都描述说SQLSERVER的存储过程较普通的SQL语句有以下优点: 1.       存储过程只在创造时进行编译即可,以后每次执行存储过程都不需再重新编译,而我们通常使用的SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度. 2.       经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用SP来封装数据库操作.当对数据库进行复杂操作时(如对多个表进行 Update,Insert,Query

通过不同的条件组装 一个sql语句

通过不同的条件组装 一个sql语句题目要求:目前需要通过不同会员信息的条件,对会员进行高级查询,这个时候就需要对sql语句的组装工作.需要查询的条件有,会员编号,会员昵称,会员帐号,会员注册时间,会员性别,条件通过GET方式传递给程序,通过任意选择这些条件进行查询,得到相应的结果.参考:会员表为user_bas 及其字段结构:查询条件和数据库字段对应关系:会员编号:id :结构:smallint(6),查询为精确查询(比如:查询编号为1 2的会员)会员昵称:nickname:结构:varchar

在mysql中修改表名的sql语句

在使用mysql时,经常遇到表名不符合规范或标准,但是表里已经有大量的数据了,如何保留数据,只更改表名呢?可以通过建一个相同的表结构的表,把原来的数据导入到新表中,但是这样视乎很麻烦.能否简单使用一个SQL语句就搞定呢?当然可以,mysql5.0下我们使用这样的SQL语句就可以了.ALTER TABLE table_name RENAME TO new_table_name例如 ALTER TABLE admin_user RENAME TO a_us

EF5中 执行 sql语句使用Database.ExecuteSqlCommand 返回影响的行数 ; EF5执行sql查询语句 Database.SqlQuery 带返回值

一: 执行sql语句,返回受影响的行数 在mysql里面,如果没有影响,那么返回行数为  -1 ,sqlserver 里面  还没有测试过 using (var ctx = new MyDbContext()) { ctx.Database.ExecuteSqlCommand("UPDATE Person SET Name = 'Michael' WHERE PersonID = 1"); } 二 : Database.SqlQuery<T>   EF5执行sql查询语句

程序中使用事务来管理sql语句的执行,执行失败时,可以达到回滚的要求。

1.设置使用事务的SQL执行语句 1 /// <summary> 2 /// 使用有事务的SQL语句 3 /// </summary> 4 /// <param name="sql"></param> 5 /// <param name="conn"></param> 6 /// <param name="tran"></param> 7 /// &l

SQLSERVER 根据传入的参数拼接sql语句字符串,反馈结果集

ALTER PROCEDURE [dbo].[usp_visit_detail](@siteid BIGINT, @Startime VARCHAR(15), @Endtime  VARCHAR(15), @Aflag  INT = 10,                                    --初始值为10,非10,则表示有传入参数 @Area   VARCHAR(20) = 'N',               -- --初始值为N,非N,则表示有传入参数 @Nflag  

关于在java中向带有IN的SQL语句中传参数的问题

今天遇到俩个问题: 1.在使用表格模型的时候,从数据库查询出来的数据赋值到Jtable的时候永远只显示最后一天记录,前面的都被覆盖了.一直在究其原因,未果,遂择其道而行之(第二个问题). 2.为了解决上面的问题,我将SQL语句的条件换成IN,目的想把所有参数一并传过去,查询所有记录后在一并显示到Jtable上,实验证明我的做法是对的.但是,一直没有搞懂IN(?)这个问号应该如何传值. SQL : String sql = " select sxh,grbm,xm,yybm,fyze,qzfbf,

SQL SERVER 一个SQL语句的执行顺序

原文:SQL SERVER 一个SQL语句的执行顺序 一个SQL 语句的执行顺序 1.From (告诉程序 来自哪张表  如果是表表达式 依旧是如此顺序) 2.Where(条件筛选  谓词筛选 ) 3.Group by(分组) 4.Having(分组  谓词筛选 ) 5.Select (表达式) 6.表达式(开窗函数 聚合函数 等等) 7.Distinct(去重复) 8.ORDER BY 9.TOP/OFFSET-FETCH 原文地址:https://www.cnblogs.com/lonely