ROW_NUMBER() OVER PARTITION 优化
ROW_NUMBER() OVER PARTITION optimization
我有以下查询:
SELECT *
FROM
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Code ORDER BY Price ASC) as RowNum
from Offers) r
where RowNum = 1
Offers table 包含大约 1000 万条记录。但是那里只有大约 4000 个不同的代码。所以我需要为每个代码获取价格最低的行,结果中只有 4000 行。
我在(代码、价格)列和 INCLUDE 语句中的所有其他列上有一个索引。
查询运行了 2 分钟。如果我查看执行计划,我会看到索引扫描有 10M 实际行。所以,我猜它会扫描整个索引以获取所需的值。
为什么 MSSQL 进行全索引扫描?是因为子查询需要整个数据吗?如何避免这种扫描?是否有 SQL 提示仅处理分区中的第一行?
还有其他方法可以优化此类查询吗?
不确定您是否会获得任何显着的性能提升,但您可能想尝试 WITH TIES 子句
例子
Select Top 1 with Ties *
From Offers
Order By Row_Number() over (Partition By Code Order By Price)
尝试在 ( Code, Price )
上创建索引而不包括其他列,然后(假设有一个唯一的 Id
列):
select L.*
from Offers as L inner join
( select Id,
Row_Number() over ( partition by Code order by Price ) as RN
from Offers ) as R on R.Id = L.Id and R.RN = 1
对较小索引进行索引扫描应该会有所帮助。
第二个猜测是明确地为每个 Code
获取具有最低 Price
的行的 Id
:获取 distinct Code
值,获取 Id
的 top 1
(以避免出现重复价格问题)Min( Price )
行 Code
,加入 Offers
以获得完整的行。同样,更紧凑的索引应该有所帮助。
在尝试了多种不同的解决方案后,我找到了使用 CROSS APPLY 语句的最快查询:
SELECT C.*
FROM (SELECT DISTINCT Code from Offers) A
CROSS APPLY (SELECT TOP 1 *
FROM Offers B
WHERE A.Code = B.Code
ORDER by Price) C
到 运行 大约需要 1 秒。
我有以下查询:
SELECT *
FROM
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Code ORDER BY Price ASC) as RowNum
from Offers) r
where RowNum = 1
Offers table 包含大约 1000 万条记录。但是那里只有大约 4000 个不同的代码。所以我需要为每个代码获取价格最低的行,结果中只有 4000 行。
我在(代码、价格)列和 INCLUDE 语句中的所有其他列上有一个索引。
查询运行了 2 分钟。如果我查看执行计划,我会看到索引扫描有 10M 实际行。所以,我猜它会扫描整个索引以获取所需的值。
为什么 MSSQL 进行全索引扫描?是因为子查询需要整个数据吗?如何避免这种扫描?是否有 SQL 提示仅处理分区中的第一行?
还有其他方法可以优化此类查询吗?
不确定您是否会获得任何显着的性能提升,但您可能想尝试 WITH TIES 子句
例子
Select Top 1 with Ties *
From Offers
Order By Row_Number() over (Partition By Code Order By Price)
尝试在 ( Code, Price )
上创建索引而不包括其他列,然后(假设有一个唯一的 Id
列):
select L.*
from Offers as L inner join
( select Id,
Row_Number() over ( partition by Code order by Price ) as RN
from Offers ) as R on R.Id = L.Id and R.RN = 1
对较小索引进行索引扫描应该会有所帮助。
第二个猜测是明确地为每个 Code
获取具有最低 Price
的行的 Id
:获取 distinct Code
值,获取 Id
的 top 1
(以避免出现重复价格问题)Min( Price )
行 Code
,加入 Offers
以获得完整的行。同样,更紧凑的索引应该有所帮助。
在尝试了多种不同的解决方案后,我找到了使用 CROSS APPLY 语句的最快查询:
SELECT C.*
FROM (SELECT DISTINCT Code from Offers) A
CROSS APPLY (SELECT TOP 1 *
FROM Offers B
WHERE A.Code = B.Code
ORDER by Price) C
到 运行 大约需要 1 秒。