我有以下观点
create view V(CategoryId, ...)
as
select 1, .... from T1 union all
select 2, .... from T2 union all
select 3, .... from T3 union all
select 4, .... from T4 union all
select 5, .... from T5 union all
...
我没有将列CategoryId
添加到下划线表中,因为每个表都有常量值,因此我无法添加Check(CategoryId = 1)
,因为列实际上不存在。
以下查询将扫描所有表。是一种让执行计划只扫描查询表中的一个的方法吗?
declare @id tinyint = (....);
select * from V where CategoryId = @id and ...
答案 0 :(得分:4)
以下查询将扫描所有表。这是一种让它的方式 执行计划只扫描查询表中的一个?
首先检查这是否真的发生了。
CREATE TABLE T1(X INT)
CREATE TABLE T2(X INT)
CREATE TABLE T3(X INT)
GO
CREATE VIEW V(CategoryId, X)
AS
SELECT 1, X
FROM T1
UNION ALL
SELECT 2, X
FROM T2
UNION ALL
SELECT 3, X
FROM T3
然后运行
SET STATISTICS IO ON;
DECLARE @id TINYINT = 1;
SELECT *
FROM V
WHERE CategoryId = @id
返回
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0
Table 'T1'. Scan count 1, logical reads 0, physical reads 0
未访问T2
或T3
。该计划看起来像
如果@id
的值与计划的该部分相关,则过滤器运算符具有启动谓词并仅在下面执行扫描。
在实际执行计划中,如果查看T2
和T3
扫描运算符的属性,则“执行次数”会显示为0
。
您还可以评估
DECLARE @id TINYINT = 1;
SELECT *
FROM V
WHERE CategoryId = @id
OPTION (RECOMPILE)