Bor*_*ort 9 sql-server-2005 sql-server-2008
在阅读这篇关于 SQL Server 中的计划缓存的文章时,我发现了一个我不知道的花絮:
...为了重用,批处理引用的对象不需要名称解析。例如,Sales.SalesOrderDetail 不需要名称解析,而 SalesOrderDetail 则需要,因为在多个架构中可能存在名为 SalesOrderDetail 的表。通常,由两部分组成的对象名称(即 schema.object)为计划重用提供了更多机会。
我正在寻找关于使用两部分对象名称的重要性的一些说明,因为“通常,两部分对象名称为计划重用提供了更多机会。”,但它首先说这是必要的。
更具体地说,我处理的大多数存储过程都在 dbo 模式中,并且只引用 dbo 对象,而没有指定 dbo 前缀。即使所有内容都使用默认模式,这些是否无法重用缓存的查询计划?
对于要重用的计划,sys.dm_exec_plan_attributes
where 中的所有属性is_cache_key=1
必须相同。这些列表如下。
acceptable_cursor_options
compat_level
date_first
date_format
dbid
dbid_execute
is_replication_specific
language_id
merge_action_type
objectid
optional_clr_trigger_dbid
optional_clr_trigger_objid
optional_spid
required_cursor_options
set_options
status
user_id
Run Code Online (Sandbox Code Playgroud)
使用两个部分名称影响的一个是 user_id
如果您在具有默认架构的用户凭据下尝试以下操作 dbo
DBCC FREEPROCCACHE;
CREATE TABLE dbo.FooBar(X int);
EXEC('SELECT * FROM FooBar');
EXEC('SELECT * FROM FooBar');
EXEC('SELECT * FROM dbo.FooBar');
EXEC('SELECT * FROM dbo.FooBar');
Run Code Online (Sandbox Code Playgroud)
然后执行以下查询
SELECT usecounts,
text,
value AS [user_id]
FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
WHERE text LIKE 'SELECT * FROM %FooBar' and attribute='user_id'
Run Code Online (Sandbox Code Playgroud)
你会看到以下结果
usecounts text user_id
----------- ----------------------------------- -------
2 SELECT * FROM dbo.FooBar -2
2 SELECT * FROM FooBar 1
Run Code Online (Sandbox Code Playgroud)
这表明当第二次运行相同的语句时,两个计划都得到了重用。sys.dm_exec_plan_attributes的文档解释了user_id
值为 -2 表示提交的批处理不依赖于隐式名称解析,可以在不同用户之间共享。这是首选方法。任何其他值表示在数据库中提交查询的用户的用户 ID。
这似乎是不正确的!从我的测试来看,它user_id
在第二种情况下实际使用的值似乎是schema_id
执行用户的默认架构的值,而不是该特定用户的标识符。EXEC
使用默认模式“dbo”在不同的登录名下再次运行这四个语句。
usecounts text user_id
----------- ----------------------------------- -------
4 SELECT * FROM dbo.FooBar -2
4 SELECT * FROM FooBar 1
Run Code Online (Sandbox Code Playgroud)
显示查询的两个版本的计划能够在用户之间重复使用。最后EXEC
在第三次登录下再次运行这四个语句,默认模式“guest”给出。
usecounts text user_id
----------- ----------------------------------- -------
6 SELECT * FROM dbo.FooBar -2
4 SELECT * FROM FooBar 1
2 SELECT * FROM FooBar 2
Run Code Online (Sandbox Code Playgroud)
表明dbo
合格查询的计划已在具有不同默认架构的用户之间成功共享,但非架构合格查询需要编译新计划。
如果您没有看到这种共享发生,请确保您正在测试的所有登录都具有相同的set_options
, language_id
, date_first
,date_format
因为它们位于开头列出的缓存键中,并且它们之间的任何差异都将阻止计划在会话之间重复使用。
归档时间: |
|
查看次数: |
1179 次 |
最近记录: |