为什么查询优化器会低估并导致数据溢出到tempdb?

问题描述 投票:0回答:1

我有一个非常简单的查询,我正在通过运行临时测试来测试它。 执行计划表明,由于估计不当,数据正在溢出到 tempdb 中。 我无法解决出现的三个警告中的任何一个:操作员在执行过程中使用 tempdb 溢出数据,溢出级别为 1 和 1 溢出线程

所有表都有覆盖索引和最新统计数据。

我尝试过使用临时表、硬编码而不是变量、重新排序 WHERE 子句,甚至通过向 JOIN 添加过滤条件来消除 WHERE 子句。

我在每次执行后使用DBCC FREEPROCCACHE中的计划句柄清除了特定的查询计划,但每次迭代都会生成相同的计划。

查询返回 10,567 条不同的记录,因此它并不是很大。

对于如何避免数据泄漏有什么建议吗?

这里是查询计划的链接brentozar.com/pastetheplan/?id=HJ1v8G03C

DECLARE
    @StartDate  datetime = '01/01/2023',
    @EndDate    datetime = '12/31/2023 23:59:59';

Select
    c.DonorTracCaseID,
    optn.Number AS OPTN,
    ti.OfferDateTime
From
    dbo.[Case] c
    INNER JOIN dbo.TriageReferral tr ON c.ID = tr.CaseID 
    INNER JOIN dbo.TriageImport ti ON tr.ID = ti.ID
    INNER JOIN PotentialDonor.DonorNumber optn ON c.DonorTracCaseID = optn.DonorTracCaseId
    INNER JOIN [Admin].ConfigureDonorNumber cdn ON optn.ConfigureDonorNumberId = cdn.ConfigureDonorNumberId
Where
    tr.IsDuplicate = 0
AND ti.OfferDateTime >= @StartDate
AND ti.OfferDateTime <= @EndDate
AND cdn.NumberDescription = 'OPTN';
sql-server performance sql-execution-plan tempdb
1个回答
0
投票

你能做的似乎不多。实际不正确的基数估计来自

DonorNumber
,可能是由于数据倾斜所致。

  • 可能值得添加以下索引,或修改现有索引。请注意,它们是多列索引,因为您似乎有许多单列索引,这没什么用。

    PotentialDonor.DonorNumber (ConfigureDonorNumberId, DonorTracCaseId) INCLUDE (Number)
    dbo.TriageReferral (IsDuplicate, CaseID)
    
  • 过滤索引或统计通常是

    DonorNumber
    上错误估计的解决方案,但不是一个选项,因为实际查找值来自
    Admin.ConfigureDonorNumber
    上的唯一联接。因此,索引视图可能是解决这个问题的唯一方法。

    CREATE OR ALTER VIEW [Admin].v_Potential_ConfigureDonorNumber
    WITH SCHEMABINDING
    AS
    SELECT
      optn.DonorTracCaseId,
      optn.Number
    FROM PotentialDonor.DonorNumber optn
    INNER JOIN [Admin].ConfigureDonorNumber cdn ON optn.ConfigureDonorNumberId = cdn.ConfigureDonorNumberId
    WHERE cdn.NumberDescription = 'OPTN'
    
    CREATE UNIQUE CLUSTERED INDEX CX ON v_Potential_ConfigureDonorNumber (NumberDescription, DonorTracCaseId)
    

    然后将查询的最后两个连接更改为 just (注意使用

    NOEXPAND

    INNER JOIN [Admin].v_Potential_ConfigureDonorNumber optn WITH (NOEXPAND) ON c.DonorTracCaseID = optn.DonorTracCaseId
    
  • 您的最后一个选择是认输并强制服务器分配更多内存,并在查询结束时这样做:

    OPTION (MIN_GRANT_PERCENT = 1);
    

    增加百分比,直到问题消失。

© www.soinside.com 2019 - 2024. All rights reserved.