【问题标题】:Should my view be much slower than my stored proc?我的视图应该比我的存储过程慢得多吗?
【发布时间】:2012-08-21 01:22:51
【问题描述】:

我有一个似乎无法完全调整的视图,因此我尝试将其转换为 proc,将查询时使用的 WHERE 条件之一移动到参数中并在派生表中使用该参数。

查看

CREATE VIEW myView
AS
SELECT     i.ItemCode
           , s.StoreID
           , ISNULL(SUM(s.TotalSales)) AS Sales
FROM       Item i
LEFT JOIN  Balance b ON i.ItemCode = b.ItemCode
LEFT JOIN  (SELECT    SUM(Quantity)
                      , StoreID
                      , ItemCode
                      , Date
            FROM      Sales
            GROUP BY  StoreID
                      , ItemCode
                      , Date) AS s    ON i.ItemCode = s.ItemCode
                                      AND s.Data >= COALESCE(b.Date, '01-01-1900)
JOIN
GROUP BY    i.ItemCode
            , s.StoreID

存储过程

CREATE PROCEDURE myProc(@StoreID INT)
AS
SELECT     i.ItemCode
           , s.StoreID
           , ISNULL(SUM(s.TotalSales)) AS Sales
FROM       Item i
LEFT JOIN  Balance b ON i.ItemCode = b.ItemCode
LEFT JOIN  (SELECT    SUM(Quantity)
                      , StoreID
                      , ItemCode
                      , Date
            FROM      Sales
            WHERE     StoreID = @StoreID
            GROUP BY  StoreID
                      , ItemCode
                      , Date) AS s    ON i.ItemCode = s.ItemCode
                                      AND s.Data >= COALESCE(b.Date, '01-01-1900)
JOIN
GROUP BY    i.ItemCode
            , s.StoreID

EXEC myProc(100) 比 SELECT * FROM myView WHERE StoreID = 100 快很多。 应该是这样吗?

注意:我知道这段代码可能没有完美的意义或无法运行——我试图通过删除其他一些 JOIN 来简化它。实际代码中唯一的实质性区别是将 WHERE 移到派生表中,我在这里已经完成了。

视图不应该在执行派生表查询时考虑我的 WHERE 并与 proc 一样快吗?

感谢您的帮助!

【问题讨论】:

  • 我正在尝试将实体框架与此查询一起使用,使用视图会更好。
  • 是的,视图可能应该更慢。首先生成视图:来自 Item、Balance 和 Sales 子查询的所有项目将被连接在一起。可能有不少记录。然后,从该集合中应用过滤器。在 proc 中,过滤器首先应用于 Sales 表,然后将这个小子集连接到其他表。因此,如果 StoreIds 的基数与 Sales 中的记录数相比较小,那么您看到的结果将是预期的。
  • 在查询视图时,有什么方法可以根据我在 WHERE 子句中提供的条件过滤派生查询?
  • 参数化视图。这个SO Question 似乎回答了这个问题,有点像你正在做的事情。由于我对sql server不熟悉,所以不能多说。

标签: sql sql-server performance stored-procedures sqlperformance


【解决方案1】:

这两个查询完全不同。区别非常微妙,但这是一行:

        WHERE     StoreID = @StoreID

视图计算所有商店的所有数据。然后过滤特定商店的结果。

存储过程版本只查看特定存储;它甚至可以有效地利用 StoreId 上的索引(如果有的话)。

【讨论】:

  • 对。我希望 SQL 能够解释我在构建执行计划时查询视图时提供的 WHERE 条件,从而过滤派生查询。您知道是否有一种方法可以过滤视图中的派生查询?
  • @BretWalker 。 . .这是我没见过的优化。不过,您可能想要的是一个表值函数。它为您提供了能够传递参数的视图语法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多