对视图的谓词:如何在视图加入之前评估谓词?

时间:2018-02-08 04:38:30

标签: sql-server

我有一个问题:

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的第一次过滤时间较晚,而第二次使用两次搜索。 Comparative execution plans

为什么是这种情况?我希望查询优化器能够比它更好地进行优化。

鉴于这种情况,我显然希望使用第二个查询,并以某种方式将谓词推送到查询的view部分。因为谓词依赖于参数,所以我不能只改变视图定义。一种选择是用表定义的函数替换视图,但是这种情况在我的数据库中被复制。还有其他方法吗?

有什么方法可以暗示,或者让我的视图中请求sqlserver使用谓词?我不知道为什么查询优化器没有查看查询并尽快推送WHERE

如果相关,则运行于: Microsoft SQL Azure (RTM) - 12.0.2000.8

0 个答案:

没有答案