繁体   English   中英

在查询中消除聚集索引扫描

[英]Eliminate Clustered Index Scan in query

我有这个查询涉及 2 个表连接。

Select  q.id, 
                         q.LastUpdatedTicksSinceEpoch,
                            q.[Type] [QuoteType],
       q.LatestFormData [FormDataJson], 
                            q.QuoteNumber, 
                            q.QuoteState,
       q.policyId,
                            p.CustomerId, 
                            p.CustomerFullName, 
                            p.CustomerAlternativeEmail,
                            p.CustomerHomePhone,
                            p.CustomerMobilePhone,
                            p.CustomerWorkPhone,
                            p.CustomerPreferredName,
       p.ProductId
                            from Quotes q
                    INNER JOIN  PolicyReadModels p on q.PolicyId=p.id
                    where
                            p.TenantId = @TenantId
                            and p.Environment = @Environment
                           and q.LastUpdatedTicksSinceEpoch > @LastUpdatedTicksSinceEpoch
         and q.QuoteState <> 'Nascent'
                            and q.QuoteNumber is not null
                            and q.IsDiscarded = 0
     ORDER BY q.LastUpdatedTicksSinceEpoch

当我运行它并获得执行计划时,我看到了聚集索引扫描 - 我想消除并使用索引搜索。

如何在此处消除聚集索引扫描? 如何构建新的 INDEX? 要为此添加更多上下文,此查询将由 12 个并行线程(12 个连接)调用,因此我需要快速和优化。

这是我的查询和执行计划:

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

在以下位置创建索引:

create index someIndex on
Quotes (LastUpdatedTicksSinceEpoch)
include (Id, Type, LatestFormData, QuoteNumber, QuoteState, PolicyId, IsDiscarded)
where IsDiscarded = 0
                      

这个

  • 按您的两个固定值过滤(QuoteNumber NOT NULL 和 IsDiscarded = 0)
  • 按 LastUpdatedTicksSinceEpoch 对数据进行排序(因为您将一个变量传递给 WHERE 子句中的那个,并且它看起来最有可能是您想要排序的
  • 包括所有其他相关字段,因此不需要返回到聚集索引(例如,成为覆盖索引)。

请注意,quote.ID 不包括在内,因为它是您的 PK(根据我在执行计划中的说法),因此隐式包含在索引中。 您可以包含它 - 根本不会造成任何伤害(例如,索引大小和性能将完全相同)。

CREATE INDEX IX_q ON Quotes 
    (
    LastUpdatedTicksSinceEpoch
    )
INCLUDE
    (
    PolicyId,
    [Type],
    QuoteState,
    LatestFormData,
    QuoteNumber,
    IsDiscarded
    )
WHERE 
    (
    QuoteNumber is not null 
    AND IsDiscarded = 0
    )

注意:我认为这可能是你能得到的最快的,但你需要小心,因为表上的索引越多意味着插入、更新和删除的速度越慢。

我经常发现可以在许多地方使用的更短的索引比这样的非常具体的索引更可取(请记住,如果像 LatexFormData 这样的某些字段很大,那么这个索引可能会变得臃肿并且对其他查询没有用)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM