-
use
master
-
go
-
-
if
exists(
select *
from sys.databases
where
name =
'test')
-
drop
database
test
-
go
-
-
--创建数据库
-
create
database
test
-
-
if
exists(
select *
from sys.tables
where
name =
't')
-
drop
table t
-
go
-
-
-
--1.创建表t
-
create
table t(i
int);
-
-
-
--2.添加100000条记录,消耗56秒
-
declare @i
int;
-
declare @
sql
varchar(
1000);
-
-
set @i =
1
-
set @
sql =
'';
-
-
while @i <= 100000
-
begin
-
set @
sql =
'insert into t values(' +
cast(@i
as
varchar) +
')'
-
begin tran
-
-
exec(@
sql)
-
commit tran
-
-
set @i = @i +
1
-
end
-
-
-
--3.1查询的统计信息
-
--但发现没有返回记录
-
select st.text,
-
SUBSTRING(st.text, (qs.statement_start_offset/
2)+
1,
-
((
CASE qs.statement_end_offset
-
WHEN
-1
THEN
DATALENGTH(st.text)
-
ELSE qs.statement_end_offset
-
END - qs.statement_start_offset)/
2) +
1)
AS statement_text,
-
qs.*
-
from sys.dm_exec_query_stats qs
-
cross
apply sys.dm_exec_sql_text(qs.sql_handle) st
-
where
cast(st.text
as
varchar)
like
'%insert into t values%'
-
-
-
-
--3.2查询的统计信息
-
--有返回,说明SQL Server在执行动态生成的语句时,已经参数化了
-
--execution_count字段的值为100000
-
select st.text,
-
SUBSTRING(st.text, (qs.statement_start_offset/
2)+
1,
-
((
CASE qs.statement_end_offset
-
WHEN
-1
THEN
DATALENGTH(st.text)
-
ELSE qs.statement_end_offset
-
END - qs.statement_start_offset)/
2) +
1)
AS statement_text,
-
qs.*
-
from sys.dm_exec_query_stats qs
-
cross
apply sys.dm_exec_sql_text(qs.sql_handle) st
-
where
cast(st.text
as
varchar)
like
'%insert into%'
-
-
-
--3.3 查看数据库是否强制参数化
-
--并没有强制参数化,说明上面是系统自动对语句进行参数化了
-
select
name,
-
is_parameterization_forced
--返回0,说明并没有强制参数
-
from sys.databases
-
where
name =
'test'
-
-
-
--3.4 再次执行后,再次执行3.2后发现,execution_count为100001
-
insert
into t
values(
100001)
-
-
--3.5 这次在语句中加了空格,execution_count为100002
-
insert
into t
values(
100002 )
-
-
-
--3.5 这次在语句中加了架构
-
--返回2条记录,一条为100002,另一个为1
-
--虽然2条数据的sql_handle、plan_handle都不相同,但是query_hash、query_plan_hash相同
-
insert
into dbo.t
values(
100003 )
-
-
-
--3.6 显示缓存的执行计划
-
--返回2条数据,一条为100002,一个为1
-
--缓存对象类型为编译计划,对象类型为Prepared
-
select *
-
from sys.dm_exec_cached_plans cp
-
cross
apply sys.dm_exec_sql_text(cp.plan_handle) st
-
where st.text
like
'%insert into%'
-
-
最后总结一下:
1.对于一些比较简单的语句,SQL Server能自动进行参数化,会自动忽略空格。
2.但当语句有不同时,比如加了对象所属的架构后,系统就没办法进行参数化了,但很有意思的是query_hash和query_plan_hash都相同,也就是说明本质上这些查询都是一样的。
所以可以通过group by这些hash值,计算编译了多少次。