首页 > 解决方案 > INDEX 用于提高包含 ROW_NUMBER OVER PARTITION 的视图的性能

问题描述

我在 SQL Server 中创建了以下视图。它在视图中使用两组ROW_NUMBER OVER PARTITION查询,因为两个引用的表将ServerName在一系列RowInsertDateTime日期/时间内多次出现相同的查询,而我只对每个表的最新行感兴趣。

返回 471 行需要 4 秒。没有一个表包含索引。我需要一些帮助来了解我可以添加哪些索引来提高视图的性能。我检查了实际的执行计划,两种排序分别负责总查询成本的 11% 和 35%。

视图定义:

CREATE VIEW ViewInSiteSuperTable 
AS
     SELECT 
         sales.ServerName,
         GETDATE() AS RowInsertDateTime,
         sales.daily_sales,
         basket.AvgBasketAmount,
         basket.AvgBasketQty,
         oos.OutOfStockCount,
         tph.transactions_per_hour,
         tph.total_transactions
     FROM
         dbo.InSiteEodSalesPerDayPerStore sales WITH (NOLOCK) 
     INNER JOIN 
         (SELECT 
              ServerName, 
              RowInsertDateTime,
              AvgBasketAmount,
              AvgBasketQty
          FROM 
              (SELECT   
                   ServerName,
                   RowInsertDateTime,
                   AvgBasketAmount,
                   AvgBasketQty,
                   ROW_NUMBER() OVER (PARTITION BY ServerName ORDER BY RowInsertDateTime DESC) rn
               FROM 
                   InSiteAvgBasketSize) q
           WHERE 
               rn = 1) basket ON basket.ServerName = sales.ServeRName
    INNER JOIN
        (SELECT 
             ServerName,
             RowInsertDateTime,
             transactions_per_hour,
             total_transactions
         FROM 
             (SELECT 
                  ServerName,
                  RowInsertDateTime,
                  transactions_per_hour,
                  total_transactions,
                  ROW_NUMBER() OVER (PARTITION BY ServerName ORDER BY RowInsertDateTime DESC) rn
              FROM 
                  InSiteTxPerHourPerDayTotals) q
         WHERE 
             rn = 1) tph ON tph.ServerName = sales.ServerName
    INNER JOIN 
        dbo.InSiteOutOfStocksAllStores oos WITH (NOLOCK) ON oos.ServerName = sales.ServerName 
    WHERE   
        sales.daily_sales_date =  DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0) 

执行计划

在此处输入图像描述

标签: sql-serverindexingview

解决方案


消除 2 个 sotrs 的指标是:

create index ix_ServerName_RowInsertDateTime on InSiteTxPerHourPerDayTotals
(ServerName asc, RowInsertDateTime desc) include(transactions_per_hour, total_transactions)

create index ix_ServerName_RowInsertDateTime on InSiteAvgBasketSize
(ServerName asc, RowInsertDateTime desc) include(AvgBasketAmount, AvgBasketQty)

但是,您应该actual execution plan在问题中包含,而不是作为图片,而是使用粘贴计划

我了解基本索引,例如删除表扫描的索引,但我真的很想了解这些索引建议背后的想法。

在这种情况下,索引不是删除 ,scan而是删除sort. 无论如何,这两个表都会被扫描,你想枚举所有行,所以你不能删除scan,但你想在每个ServerName组中枚举,它是第一个index key,你想RowInsertDateTime在每个组中排序,所以它是第二个index key. 这两个字段在排序时已经拥有您想要的:它们在 s 组中是有序的。

其他字段included不需要按顺序排列,但没有它们,索引不适covering用于您的查询,即服务器将对基表进行查找以获取它们,因为它们存在于select子句中。


推荐阅读