partition 和 max 的缓慢查询性能问题

slow query performance issue with partition and max

这是一个性能很差的查询...我做错了什么? 请帮助我它在我的系统中被执行了很多次,解决这个问题会给我一个通往天堂的阶梯

我用 sp_Blitz 检查了系统,没有发现致命问题

这里是查询:

SELECT MAX(F.id) OVER (PARTITION BY idstato ORDER BY F.id DESC) AS id
FROM jfel_tagxml_invoicedigi F
     INNER JOIN jfel_invoice_state S ON F.id = S.idinvoice
WHERE S.idstato = @idstato
  AND S.id = F.idstatocorrente
  AND F.sequence_invoice % @number_service_installed = @idServizio
ORDER BY F.id DESC,
         F.idstatocorrente OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY;

这是查询计划

https://www.brentozar.com/pastetheplan/?id=SyYL5JOeE

我可以私信你我的系统属性

更新: 做了一些修改,它更好,但我认为它可以更好...... 这是新查询:

SELECT MAX(F.id) AS id
FROM jfel_tagxml_invoicedigi F
     INNER JOIN jfel_invoice_state S ON F.id = S.idinvoice
WHERE S.idstato = @idstato
  AND S.id = F.idstatocorrente
  AND F.sequence_invoice % @number_service_installed = @idServizio;

以及新计划: https://www.brentozar.com/pastetheplan/?id=SJ-5GDqeE

更新: 做了一些修改,它更好,但我认为它可以更好...... 这是新查询:

SELECT top 1 F.id as id 
FROM jfel_tagxml_invoicedigi AS F 
INNER JOIN jfel_invoice_state AS S 
ON F.idstatocorrente = S.id
WHERE S.idstato= 1 AND S.id = F.idstatocorrente 
and S.datastato > dateadd(DAY,-5,getdate())
AND F.progressivo_fattura % 1 = 0
ORDER BY S.datastato

还有新的新计划 https://www.brentozar.com/pastetheplan/?id=S1xRkL51S

我认为您需要 NONCLUSTERED INDEX 用于您上面描述的查询。

如果您对 INDEX 没有任何想法,我的意思是您无法确定 table NONCLUSTERED INDEX 需要的 字段,那么简单地说,您只需从 SQL Server 2008 Management Studio 和 SQL 服务器智能创建一个执行计划即可为您提供缺少的索引详细信息 并显示绿色文本,其中包含缺失索引的详细信息。

您可以将鼠标指针移到缺失的索引文本上,SQL Server 2008 Management Studio 智能将显示创建缺失索引所需的 T-SQL 代码,或者您可以按鼠标 right-click 在缺失索引文本上然后 select 列表中的缺失索引详细信息选项以查看缺失索引的详细信息。

更多信息,可以访问这篇文章Create Missing Index From the Actual Execution Plan

希望此解决方案对您有所帮助。

按用于对性能产生负面影响的计算字段进行过滤。您可以先执行其他过滤器,最后一步执行计算过滤器,以匹配更少的行。也许它会填充 TEMPDB,因为它将在那里存储中间记录集,但在这种情况下,您要么增加它的大小,要么使用其他方法。
这是你写的第二个查询(也许你需要调整它,我只是在 Notepad++ 中写的:

SELECT MAX(id) AS id
FROM (
    SELECT F.id, F.sequence_invoice % @number_service_installed as [idServizio]
    FROM jfel_tagxml_invoicedigi F
         INNER JOIN jfel_invoice_state S ON F.id = S.idinvoice
    WHERE S.idstato = @idstato
        AND S.id = F.idstatocorrente
        -- AND F.sequence_invoice % @number_service_installed = @idServizio
)
WHERE idServizio = @idServizio
;

除了子查询,您还可以尝试临时 table 或 CTE,也许其中一个是明显的赢家,如果您想要最佳性能,则值得一试。

数据计算为Non-Sargable,您可以尝试使用带有 OPTION RECOMPILE 的变量:

DECLARE @d Date
SET @d = dateadd(DAY,-5,getdate())

SELECT top 1 F.id as id 
FROM jfel_tagxml_invoicedigi AS F 
INNER JOIN jfel_invoice_state AS S 
ON F.idstatocorrente = S.id
WHERE S.idstato= 1 AND S.id = F.idstatocorrente 
and S.datastato > @d
AND F.progressivo_fattura % 1 = 0
ORDER BY S.datastato
OPTION (RECOMPILE)

所有 Window 聚合具有非常大的性能损失。尝试将此 window 滑动机制置于数据库之外(即在您的应用程序 RAM 中)将是优化它的通用方法。

否则,您可以尝试为 each 数据库部分提供更多 RAM(在 PostgreSQL 中,您可以通过参数调整它。在其他数据库中,您可能会也可能不会到)。

它花费很长时间(很慢)的主要原因是它调用了已排序 table 的排序和具体化。