INDEX 用于提高包含 ROW_NUMBER OVER PARTITION 的视图的性能
Posted
技术标签:
【中文标题】INDEX 用于提高包含 ROW_NUMBER OVER PARTITION 的视图的性能【英文标题】:INDEX to improve performance for View containing ROW_NUMBER OVER PARTITION 【发布时间】:2018-12-10 04:42:31 【问题描述】:我在 SQL Server 中创建了以下视图。它在视图中使用两组ROW_NUMBER OVER PARTITION
查询,因为两个引用的表将在RowInsertDateTime
日期/时间范围内多次出现相同的ServerName
,我只对每个表的最新行感兴趣桌子。
返回 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)
执行计划
【问题讨论】:
【参考方案1】:表示消除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
,而不是图片,而是使用Paste The Plan
我了解基本索引,例如用于删除表扫描的索引,但是 真的很想了解这些指数背后的想法 建议。
在这种情况下,索引不是删除scan
,而是删除sort
。无论如何,这两个表都会被扫描,你想枚举所有行,所以你不能删除scan
,但你想在每个ServerName
组中枚举,它是第一个index key
,你想按RowInsertDateTime
在每个组内,所以它是第二个index key
。这两个字段在排序时已经有了你想要的:它们在 s 组中是有序的。
其他字段为included
,因为它们不需要按顺序排列,但没有它们,索引就不是covering
用于您的查询,即服务器将查找基表以获取它们,因为它们存在于@ 987654333@子句。
【讨论】:
谢谢你 sepupic,我会调查你的回复。我很抱歉没有使用 Paste The Plan 来粘贴我的实际执行计划,但是在我的辩护中,在你发布它之前我不知道这个网站的存在,所以我只能做我知道的事情。现在我意识到该网站的存在,我将从现在开始使用它。 谢谢 - 这工作。查询现在是亚秒级的。 sepupic,如果你不介意告诉我你是如何得出这些指数的理性的?我了解基本索引,例如删除表扫描的索引,但我真的很想了解这些索引建议背后的想法。这样,我可以通过了解您是如何得出这些结论的,而不仅仅是复制粘贴,而是“学会钓鱼”。以上是关于INDEX 用于提高包含 ROW_NUMBER OVER PARTITION 的视图的性能的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 中用于插入的 ROW_NUMBER() 等效项[重复]
ROW_NUMBER() OVER函数的基本用法,也可用于去除重复行