我对为什么我的查询没有使用我认为是选择性索引的东西感到非常困惑。
我的模型由索赔、联系人和电话号码组成。每个索赔有 1 个联系人,每个联系人都有许多电话号码。索赔可以有状态,电话号码有类型。
我在状态的 Claim 上添加了一个索引,它包括 ContactID。
create index Status on tClaim(Status) include (Name,ContactID)
Run Code Online (Sandbox Code Playgroud)
我在电话上为 ContactID 和类型添加了一个索引,其中包括号码。
create index ContactID_Type on tContactPhone(ContactID,Type) include (Number)
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个查询,该查询返回状态为“赢得”的所有索赔以及索赔联系人的相应“家庭电话”。我已经尝试了 2 种方法。一种包括加入通讯录,另一种没有。两者都不会产生我期望的计划。
select
c.ID,
c.Name,
p.Number
from
tClaim c
left join tContactPhone p on
c.ContactID=p.ContactID and p.Type='Home'
where
c.Status = 'Won'
select
c.ID,
c.Name,
p.Number
from
tClaim c
inner join tContact co on
co.id=c.ContactID
left join tContactPhone p on
co.ID=p.ContactID and p.Type='Home'
where
c.Status = 'Won'
Run Code Online (Sandbox Code Playgroud)
我回来的计划拒绝使用 tContactPhone.ContactID_Type。它建议按类型索引,这没有意义,因为它似乎没有 ContactId 选择性。
这是我用来创建要测试的示例数据集的脚本。请注意我的实际数据集要大得多,命名得更好,并且有更多的字段;但这被提炼出来以复制我的情况 [AKA 我什至不喜欢命名约定和数据生成,但它完成了工作:)] …
index sql-server execution-plan cardinality-estimates sql-server-2019
我们有一个多租户数据库。FirmID 是分区键,我们有很多不同的公司。
我遇到了一个参数嗅探问题,我很忙。
我宁愿不在查询中使用任何 [Options]。
我最近的想法是更改我为公司使用的参数的名称。在下面的代码段中,您将看到我将其命名为 @Firm611 而不是使用 @FirmID,其中 611 是 ID 的实际公司。这将为我提供每个公司的唯一查询。
select
c.ID [_cid],
c.Name [Name]
from vwClaims c with(nolock)
where c.FirmID=@Firm611
and (c.Name is not null and c.Name!='')
select
c.ID [_cid],
c.Name [Name]
from vwClaims c with(nolock)
where c.FirmID=@Firm625
and (c.Name is not null and c.Name!='')
Run Code Online (Sandbox Code Playgroud)
运行 Brent Ozar 的 sp_BlitzCache 后,我发现它只是编译为相同的查询并导致重复的缓存条目:
我的问题是我读的结果对吗?即使我更改了参数名称,它真的还在使用相同的计划和参数嗅探吗?