覆盖索引问题

Tom*_*Tom 4 performance index sql-server t-sql index-tuning query-performance

我有以下查询

Select  Pt.PRODID, PT.INVENTREFID,  Inv.ItemName, PT.ItemID, Configid,  Pt.QTYSCHED,
PT.DLVDATE,  Pt.CREATEDDATETIME, pt.SCHEDEND,
 CASE Left(PT.INVENTREFID, 3)
     WHEN 'SJB' THEN ST.SALESNAME
     WHEN 'WJB' THEN 'Sub - Assembly'
     ELSE 'Stock'
  END as CustomerName
from Dynamicsv5Realtime.dbo.PRODTABLE PT
Join Dynamicsv5Realtime.dbo.Inventdim ID
On PT.InventdimId = ID.InventdimID
and PT.Dataareaid = ID.dataareaid
Join Dynamicsv5Realtime.dbo.INVENTTABLE Inv
On Inv.itemid = PT.ItemId
Left Join Dynamicsv5Realtime.dbo.SALESTABLE ST
ON ST.SalesId = PT.INVENTREFID
and ST.Dataareaid = PT.dataareaid
where pt.PRODSTATUS in(2,3,4)
and PT.DATAAREAID = 'AJB'
Order by 7 
Run Code Online (Sandbox Code Playgroud)

当我想改进它时,我想出了以下索引

CREATE NONCLUSTERED INDEX [INDEX_2]
ON [dbo].[PRODTABLE] ([INVENTREFID],[DATAAREAID],[INVENTDIMID],[PRODSTATUS])
INCLUDE ([PRODID],[ItemID],[QTYSCHED],[DLVDATE],[CREATEDDATETIME],[SCHEDEND])
Run Code Online (Sandbox Code Playgroud)

然而,这并不像缺少索引 DMV 提出的以下有效

CREATE NONCLUSTERED INDEX [INDEX_1]
ON [dbo].[PRODTABLE] ([DATAAREAID],[PRODSTATUS])
INCLUDE ([ITEMID],[QTYSCHED],[DLVDATE],[SCHEDEND],[INVENTREFID],[PRODID],[INVENTDIMID],    [CREATEDDATETIME]) 
Run Code Online (Sandbox Code Playgroud)

我想知道什么时候将列放在索引本身而不是索引的 Include 部分更有效?

可能感谢

Aar*_*and 9

非常普遍且非技术性地,如果您打算在WHERE子句中使用该列(或以其他方式过滤/查找),并且INCLUDE仅用于避免查找(我喜欢称其为“一起来兜风”)。当然,总有例外:

  • 由于大小,您不能总是在键中包含列;
  • 由于基数,这可能无关紧要;或者,
  • 它可能不会影响计划,因为您必须将它放在键中以允许索引继续满足其他查询语义。

在某些情况下,INCLUDEd 列可以很好地满足过滤器,并且在很多情况下,更改索引可能有助于此特定查询,但可能会对您的其余工作负载造成严重破坏。您应该始终针对代表尽可能多的完整业务周期的整个工作负载测试索引更改,而不是依赖于缺失的索引 DMV 或您自己的分析,这似乎集中在单个查询上。

我相信 Paul White 会给出更详细、技术上更准确的回应。