我有一个问题:
SELECT TOP 1 * FROM vwTimeBlocks
WHERE vwTimeBlocks.id = @id
AND vwTimeBlocks.organization = @org
organization
在视图中的某些表中编入索引。我期望 {<1}}将在之前 任何WHERE
之前的基础表上进行评估,但事实并非如此:
执行计划表明JOINs
正在WHERE
的结果上应用vwBlocks
。替换vwBlocks
定义给了我:
SELECT TOP 1 * FROM
( SELECT ... all the things...
FROM tblTimeBlocks
LEFT OUTER JOIN tblA
ON tblA.id = tblTimeBlocks.F
AND tblTimeBlocks.B = 1000
LEFT OUTER JOIN tblB
ON tblB.id = tblTimeBlocks.F
AND tblTimeBlocks.B = 2000
) AS subTimeBlocks
WHERE subTimeBlocks.id = @timeblock AND subTimeBlocks.organization = @org;
将此执行计划与原始查询进行比较表明它们完全相同。但是,当我将WHERE
子句放在子查询中时:
SELECT TOP 1 * FROM
( SELECT ... all the things...
FROM tblTimeBlocks
LEFT OUTER JOIN tblA
ON tblA.id = tblTimeBlocks.F
AND tblTimeBlocks.B = 1000
LEFT OUTER JOIN tblB
ON tblB.id = tblTimeBlocks.F
AND tblTimeBlocks.B = 2000
WHERE subTimeBlocks.id = @timeblock AND subTimeBlocks.organization = @org
) AS subTimeBlocks
整体查询成本下降,新查询的执行计划要好得多;这是一个比较,最高执行计划显示子查询外的WHERE
,子查询中显示WHERE
的底部计划。
请注意,查询的相对成本为91%-9%,organization
的第一次过滤时间较晚,而第二次使用两次搜索。
为什么是这种情况?我希望查询优化器能够比它更好地进行优化。
鉴于这种情况,我显然希望使用第二个查询,并以某种方式将谓词推送到查询的view
部分。因为谓词依赖于参数,所以我不能只改变视图定义。一种选择是用表定义的函数替换视图,但是这种情况在我的数据库中被复制。还有其他方法吗?
有什么方法可以暗示,或者让我的视图中请求sqlserver使用谓词?我不知道为什么查询优化器没有查看查询并尽快推送WHERE
。
如果相关,则运行于:
Microsoft SQL Azure (RTM) - 12.0.2000.8