首页 > 解决方案 > 查询不使用多对多关系上的索引

问题描述

我有以下查询:

select V.VisitID
from Visit V
inner join VisitDrug VD on V.VisitID = VD.VisitID
inner join Lookup.Drug D on VD.DrugID = D.DrugID
where V.StartDate >='2019-03-27 13:00:00.0000000 +00:00'
and V.StartDate <='2020-03-31 12:59:59.9990000 +00:00' 

我不明白的是,每当在 VisitDrug 上进行连接操作时,它必须对表中的所有行进行全扫描,而不仅仅是那些适用的 VisitID。

目前的指标是:

ALTER TABLE [dbo].[VisitDrug] ADD  CONSTRAINT [PK_VisitDrug] PRIMARY KEY CLUSTERED 
(
    [VisitID] ASC,
    [DrugID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]
GO

CREATE NONCLUSTERED INDEX [IDX_VisitDrug_DrugID_VisitID] ON [dbo].[VisitDrug]
(
    [DrugID] ASC,
    [VisitID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
GO

执行计划是 - https://www.brentozar.com/pastetheplan/?id=Hy6QLqT8I

通过阅读其他问题,我相信索引是正确的,但没有被使用。

标签: sqlsql-servertsql

解决方案


因为这个查询需要大量的访问,优化器决定在 Visit.StartDate 上读取索引上的日期范围会更便宜,然后对结果进行排序,然后使用 VisitDrug 进行 MERGE JOIN。另一种方法是在 PK_VisitDrug 上执行 49,914 次单独的索引查找,总共 150,000-200,000 个逻辑 IO。

您可以通过指定LOOP JOIN来测试另一个计划。


推荐阅读