我在 Azure SQL DB 中运行以下查询:
SELECT
[TransactionID],
[TrackingNumber],
TRY_CAST([EventCode] as int) as EventCode,
[EventDesc] ,
[EventTime],
[EventCountry],
[EventState],
[EventCity],
[EventPostCode],
[SpecialOperDesc],
[Reference]
FROM [dbo].[MyTable]
with (index = IX_EventTime_TrackNum_Reference)
WHERE EventTime>= dateadd(d,-15,getdate())
AND LEN(TrackingNumber) >= 22
AND Reference IS NOT NULL
强制它使用IX_EventTime_TrackNum_Reference
带有 Index Hint 的非聚集索引,直到最近它才起作用。执行计划是非聚集索引查找加上聚集索引上的查找。
现在它尝试对现有的非聚集列存储索引使用列存储索引扫描。我可以使用以下代码实时查看:
exec sp_WhoIsActive @get_plans = 2
性能变差,因为非聚集列存储索引的大小比 IX_EventTime_TrackNum_Reference 大得多,并且它在增量存储中有一些数据。SQL DB 相对较小,存储速度很慢。
是什么导致查询忽略索引提示?以及如何强制它IX_EventTime_TrackNum_Reference
再次使用?
重现问题中描述的行为的一种方法是使用Plan Guide强制执行列存储计划。也许令人惊讶的是,带有 showplan 提示的 Plan Guide 可以强制执行不遵守索引提示的计划。
db<>fiddle 演示
一旦具有强制形状的计划被查询存储捕获,该计划也可以在那里强制执行。这种强制执行将在原始计划指南被删除后继续存在,让您陷入一种令人困惑的情况,即完全不清楚提示语句如何生成不使用该索引的计划。
还有一些其他机制可能会导致索引提示被忽略,但我尚未验证这些机制。如果没有执行计划,您比我们更有能力调查原因。怀疑主要是查询存储启用,例如自动调整、计划回归和更正、CE 反馈提示,以及可能的 QS 提示(尽管我无法立即想到使用该机制)。