Sql Server-执行计划

1.每次执行sql语句都会生成执行计划并缓存起来,因为生成执行计划也需要时间开销,因此重用执行计划将能提高性能,并节省缓冲区空间。我们可以使用sys.dm_exec_cached_planssys.dm_exec_sql_textsys.dm_exec_query_plan来查询缓存的执行计划。

以下实验语句每次执行前需要执行DBCC freeproccache来清空计划缓存

2.查询执行计划语句

select 
    b.[text],
    a.usecounts,
    a.cacheobjtype,
    a.objtype,
    c.query_plan,
    a.size_in_bytes
from sys.dm_exec_cached_plans a
CROSS APPLY sys.dm_exec_sql_text(a.plan_handle) b
CROSS APPLY sys.dm_exec_query_plan(a.plan_handle) c

说明:

  text:代码sql语句

  usecounts:缓存使用次数

  objtype:

    Prepared 预定义语句,使用参数化查询的sql语句

           Adhoc 即席查询,没有参数话的查询

3.测试

    3.1 执行3次下面语句

select * from Person.Address where AddressID = 1

     结果如下,看第2、3条,Adhoc和Prepared分别被执行3次和1次,说明执行计划被重用了。

     3.2 执行下面3个语句

select * from Person.Address where AddressID = 1
go
select * from Person.Address where AddressID = 2
go
select * from Person.Address where AddressID = 3
go

    结果如下,分别为每个Adhoc查询生成了一个计划缓存

     3.3 执行下面参数话查询2次

exec sp_executesql Nselect * from Person.Address where AddressID = @AddressID,N@AddressID int,@AddressID=1

    结果日下,计划缓存被使用了2次

    3.4  执行下面语句

exec sp_executesql Nselect * from Person.Address where AddressID = @AddressID,N@AddressID int,@AddressID=1
go
exec sp_executesql Nselect * from Person.Address where AddressID = @AddressID,N@AddressID int,@AddressID=2
go

    结果如下,当查询参数值不同时,计划也被重用了

    3.5 执行下面语句

select * from Person.Address where City = San Francisco
go
select * from Person.Address where City = Dallas
go

    结果如下,adhoc计划重新生成了。所以在后台代码里写sql语句的时,如果是拼接语句的时候,如果是字符串,且长度不一致时,则不会重用执行计划,原因是对sql语句进行hash计算,根据计算结果去找是否存在执行计划,所以一个字符差别就会导致计划不能重用。

    3.6 执行下面语句

exec sp_executesql Nselect * from Person.Address where City = @City,N@City nvarchar(100),@City=San Francisco
go
exec sp_executesql Nselect * from Person.Address where City = @City,N@City nvarchar(100),@City=Dallas
go

    结果如下,当使用参数话查询的时候,计划被重用了。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。