Tsql 分区优化上的行数()
我有以下疑问:Tsql 分区优化上的行数(),tsql,sql-server-2012,query-performance,Tsql,Sql Server 2012,Query Performance,我有以下疑问: SELECT * FROM ( SELECT *, ROW_NUMBER() OVER(PARTITION BY Code ORDER BY Price ASC) as RowNum from Offers) r where RowNum = 1 提供的表包含大约1000万条记录。但是那里只有大约4000个不同的代码。所以我需要得到每个代码价格最低的行,结果中只有4000行 我在(代码、价格)列上有一个索引,包含语句中的所有其他列 查询运行2分钟
SELECT *
FROM
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Code ORDER BY Price ASC) as RowNum
from Offers) r
where RowNum = 1
提供的表包含大约1000万条记录。但是那里只有大约4000个不同的代码。所以我需要得到每个代码价格最低的行,结果中只有4000行
我在(代码、价格)列上有一个索引,包含语句中的所有其他列
查询运行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
列):
对较小的索引进行索引扫描应该会有所帮助
第二种猜测是为每个
code
明确地获取Id
最低价格行的Id
:获取distinct code
值,获取top 1
的Id
(避免重复价格问题)Min(价格)
行的code
,加入提供的
以获得完整的行。同样,更紧凑的索引应该会有所帮助。在尝试了多种不同的解决方案后,我发现了使用交叉应用语句的最快查询:
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秒。子查询本身是否包含表扫描?@AaronDietz是的,它包含。它需要为每一行设置排名,这似乎是合乎逻辑的。也许我想让MSSQL优化器做所有事情,这是“为什么MSSQL做整个索引扫描?”问题的答案。这似乎需要2分钟。我会寻找其他正在发生的事情。尝试使用nolock-通常不是一个好的解决方案,但会指出锁是否是问题所在。对索引进行碎片整理。@Papazzi我尝试了(NOLOCK)和(RECOMPILE)选项,但没有帮助您需要从“提供”表中选择哪些字段。?为什么不对代码和价格进行分组查询,然后将代码和价格返回到offers表呢?第一种解决方案的速度要慢得多。你的第二次猜测是什么意思?问题是以组中最小的价格获取记录的Id。我尝试使用分区和行数来实现这一点,但速度很慢。其目的是鼓励查询优化器以最佳方式使用索引。如果它在代码
值上搜索(代码,价格)
上的索引,则第一个匹配也将为价格
提供最小值。然后,它可以访问整行并返回所需的数据。没有包含列的索引是否会提高原始查询的性能?(检查执行计划以查看是否正在使用索引。)另一种方法是使用触发器来维护唯一code
值的表,以避免distinct
的开销。在您的情况下,您需要前1行,在我的情况下,我需要前8行。。。所以我需要一个外部连接,而不是交叉应用。
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