如何在sql server中优化视图以提高速度

时间:2010-04-29 07:11:30

标签: sql sql-server-2005 performance tsql views

我为我的项目创建了视图现在我想为了速度目的优化它们...我怎样才能确定视图可以优化?是指数有用的....

let's say the following example...

    SELECT        dbo.vw_WebInventory.skref AS SaleID, dbo.vw_WebInventory.lot_number AS LotNumber, dbo.vw_WebInventory.Description, 
                             dbo.vw_WebInventory.Image AS HasImage, dbo.vw_WebInventory.Sold, dbo.vw_WebInventory.Withdrawn, dbo.vw_WebTopBids.TopBid, 
                             ISNULL(dbo.vw_WebInventory.Mins_Extend_y, 0) AS BidTimeExtend, dbo.Sale.SaleTypeID, dbo.Sale.ClosingDate, dbo.vw_WebInventory.ExDate, 
                             dbo.vw_WebInventory.CurrDate, CASE WHEN vw_WebInventory.ExDate > ISNULL(vw_WebInventory.LotClosingDate, Sale.ClosingDate) 
                             THEN 1 ELSE 0 END AS ShowBidMessage
    FROM            dbo.vw_WebInventory INNER JOIN
                             dbo.Sale ON dbo.vw_WebInventory.skref = dbo.Sale.SaleID LEFT OUTER JOIN
                             dbo.vw_WebTopBids ON dbo.vw_WebInventory.skref = dbo.vw_WebTopBids.CatNumber AND dbo.vw_WebInventory.lot_number = dbo.vw_WebTopBids.LotNumber

其中vm_webTopBids和vm_WebInventory是两个不同的视图...... 是否可以优化此视图?

3 个答案:

答案 0 :(得分:19)

嵌套调用其他视图的视图是一种非常糟糕的性能技术。由于它无法编入索引,因此必须调用整个底层视图才能获得top返回的一条记录。另外,最终你获得了足够的图层,并且你达到了你可以在一个视图中调用多少个表的限制(如果view1调用view2和view3并且两个都调用相同的底层表,你加入它们两次而不是一次,这通常是不好的停止从视图中调用视图,否则很快就会出现一个无法使用的系统。

我们正在完全重新设计这样的系统,因为应用程序开发人员这样做了,价值数百万美元的客户端将离开我们,除非性能提高,我们无法通过这种结构改进它,所以现在我们面临着完全重新设计,客户将不会支付,因为错误是我们的。不要走这条路。现在停下来调用视图的视图非常非常糟糕。

答案 1 :(得分:3)

视图是一个扩展到外部查询的宏。除非它是索引视图并且您有企业版,否则它将被忽略。

因此,如果你加入3个视图并且每个视图使用5个表,那么你就有15个表的大连接。

最好的选择是Database Tuning Advisor或缺少索引脚本:

SELECT
    CONVERT(decimal(28, 1), migs.avg_total_user_cost * migs.avg_user_impact *
    (migs.user_seeks + migs.user_scans)) AS improvement_measure,
    'CREATE INDEX missing_index_' + CONVERT(varchar, mig.index_group_handle) +
    '_' + CONVERT(varchar, mid.index_handle) + ' ON ' + mid.statement + ' (' +
    ISNULL(mid.equality_columns, '') +
    CASE WHEN mid.equality_columns IS NOT NULL AND
              mid.inequality_columns IS NOT NULL THEN ','
         ELSE ''
    END + ISNULL(mid.inequality_columns, '') + ')' + ISNULL(' INCLUDE (' +
                                                            mid.included_columns +
                                                            ')', '') AS create_index_statement,
    migs.*,
    mid.database_id,
    mid.[object_id],
    mig.index_group_handle,
    mid.index_handle
FROM
    sys.dm_db_missing_index_groups mig INNER JOIN 
    sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle INNER JOIN
    sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle
WHERE
    CONVERT(decimal(28, 1), migs.avg_total_user_cost * migs.avg_user_impact *
    (migs.user_seeks + migs.user_scans)) > 10 AND
    database_id = DB_ID()
ORDER BY
    migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks +
                                                       migs.user_scans) DESC

编辑后,例如

您正在视图顶部嵌套视图。视图本身无法进行优化。

如上所述,这不能编入索引

答案 2 :(得分:2)

在这种情况下,视图无法编入索引,因为它包含OUTER JOIN。

有关索引视图及其(许多)限制的信息,请参阅此文章:http://technet.microsoft.com/en-us/library/cc917715.aspx