在表示级别,我从几个具有相同结构的数据库中收集数据:
CREATE VIEW [dbo].[TestCrossView]
AS
(
SELECT
ID,
Result.SText,
Result.DbName
FROM ( SELECT
CAST(0 AS INT) AS ID,
CAST('' AS NVARCHAR (100)) AS [SText],
CAST('' AS sysname) AS [DbName]
UNION
SELECT
[id],
[SText],
[DbName] AS [DbName]
FROM [DbTestCheckCross1]..TableSession
UNION
SELECT
[id],
[SText],
[DbName] AS [DbName]
FROM [DbTestCheckCross2]..TableSession
UNION
SELECT
[id],
[SText],
[DbName] AS [DbName]
FROM [DbTestCheckCross3]..TableSession ) AS Result
);
接下来,我按数据库名称执行查询过滤:
DECLARE @DbName sysname = N'DbTestCheckCross1'
SELECT TOP (1000) tcv.[ID]
,tcv.[SText]
,tcv.[DbName]
FROM [DbTestCheckCrossMain].[dbo].[TestCrossView] tcv
WHERE DbName = @DbName
在查询计划中,我看到了视图内所有数据库的扫描。
如果这样的查询运行了很长时间,那么需要模式锁的查询将等待该查询完成。
OPTION (RECOMPILE)一个提示或在过滤器中指定一个常数可以解决这个问题。
还有其他方法可以强制引擎切断不必要的数据库吗?
不提供切片;)


查询计划中的扫描运算符位于属性定义启动表达式的过滤器后面,例如:
这意味着在运行时,只有在相应的过滤器允许它通过时才会执行扫描(启动谓词将为 True)。
在 Concatenation 中组合的四个分支中,实际上只有一个(选定的)提供具有变量指定值的数据
只有选定的表扫描具有非零执行次数
对于其他扫描运算符,它等于零
但是,有一个细微差别。在开始查询之前,执行引擎将在参与查询的所有表上设置Sch-S锁(模式稳定性)(无论是否从特定表中读取数据)。因此,在查询结束之前,所有需要 Sch-M 锁(模式修改)的事情都无法
ALTER在TRUNCATE表上进行。如果您需要尽可能避免这种情况,那么在这种情况下,带有常量的选项可能是最好的(或者与动态查询相同)。选项 c
RECOMPILE不太理想,但如果查询的编译执行起来相对便宜,它可能不会那么糟糕。请注意,Sch-S锁也在编译时设置。用一个常数 or
RECOMPILE,当不需要的表完全超出计划时,不需要的锁时间自然会更少。有时不可能满足所有要求,您必须根据更重要的因素选择合理的折衷方案。