由于此查询中定义的提示,查询处理器无法生成查询计划

Mar*_*lli 4 index optimization execution-plan filtered-index sql-server-2016

有一个类似的问题,但不一样:

查询处理器无法生成查询计划

我有以下查询和以下过滤索引,但我看不出该查询无法使用下面描述的过滤索引的任何原因:

- 查询 - 使用max列或仅使用列都没有关系,它不喜欢索引提示

SELECT -- MAX(AC1.changeDate)   
          AC1.changeDate
          FROM [dbo].[applicationStateChange]  AS ac1  WITH(INDEX(FI_ASC_ChangeDate))  
          WHERE ac1.applicationID = 130002
          AND AC1.newStatus = 'PLC'  
Run Code Online (Sandbox Code Playgroud)

-- 这是我的过滤索引 - 这个索引只是为了优化上面的查询

CREATE NONCLUSTERED INDEX FI_ASC_ChangeDate  
ON [dbo].[applicationStateChange] (   applicationID DESC)  
INCLUDE ( [changeDate] )
WHERE newStatus = 'PLC'  
WITH (  PAD_INDEX = OFF, FILLFACTOR = 100  , SORT_IN_TEMPDB = OFF , IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = On, 
DROP_EXISTING = ON, 
DATA_COMPRESSION=PAGE, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) 
ON [NONCLUSTERED_INDEXES]
Run Code Online (Sandbox Code Playgroud)

当我运行查询(包括 )时index hint,我收到以下错误消息:

在此处输入图片说明

消息 8622,级别 16,状态 1,行 455 由于此查询中定义的提示,查询处理器无法生成查询计划。在不指定任何提示且不使用 SET FORCEPLAN 的情况下重新提交查询。

有遗漏吗?

-- 将列添加newStatus到索引中并没有解决问题,无论是在索引中还是在包含中:

    CREATE NONCLUSTERED INDEX FI_ASC_ChangeDate  
    ON [dbo].[applicationStateChange] (   applicationID DESC, newStatus ASC)  
    INCLUDE ( [changeDate] )
    WHERE newStatus = 'PLC'  
    WITH (  PAD_INDEX = OFF, FILLFACTOR = 100  , SORT_IN_TEMPDB = OFF , IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = On, 
    DROP_EXISTING = ON, 
    DATA_COMPRESSION=PAGE, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) 
    ON [NONCLUSTERED_INDEXES]


CREATE NONCLUSTERED INDEX FI_ASC_ChangeDate  
ON [dbo].[applicationStateChange] (   applicationID DESC)  
INCLUDE ( [changeDate],newStatus )
WHERE newStatus = 'PLC'  
WITH (  PAD_INDEX = OFF, FILLFACTOR = 100  , SORT_IN_TEMPDB = OFF , IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = On, 
DROP_EXISTING = ON, 
DATA_COMPRESSION=PAGE, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) 
ON [NONCLUSTERED_INDEXES]
Run Code Online (Sandbox Code Playgroud)

可以是兼容模式吗?

我注意到如果我filter从索引中删除,那么查询会接受它。但这不是我想要的。

CREATE NONCLUSTERED INDEX FI_ASC_ChangeDate  
ON [dbo].[applicationStateChange] (   applicationID DESC,newStatus
)  
INCLUDE ( [changeDate])
--WHERE newStatus = 'PLC'  
WITH (  PAD_INDEX = OFF, FILLFACTOR = 100  , SORT_IN_TEMPDB = OFF , IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = On, 
DROP_EXISTING = ON, 
DATA_COMPRESSION=PAGE, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) 
ON [NONCLUSTERED_INDEXES]
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

这是有问题的表的定义:

IF OBJECT_ID('[dbo].[applicationStateChange]') IS NOT NULL 
DROP TABLE [dbo].[applicationStateChange] 
GO
CREATE TABLE [dbo].[applicationStateChange] ( 
[applicationID]      INT                              NOT NULL,
[changeDate]         DATETIME                         NOT NULL,
[oldStatus]          CHAR(3)                              NULL,
[newStatus]          CHAR(3)                              NULL,
[oldStatusReasonID]  INT                                  NULL,
[newStatusReasonID]  INT                                  NULL,
[oldStatusReason]    VARCHAR(60)                          NULL,
[newStatusReason]    VARCHAR(60)                          NULL,
[oldOnHold]          BIT                                  NULL,
[newOnHold]          BIT                                  NULL,
CONSTRAINT   [PK_applicationStateChange]  PRIMARY KEY CLUSTERED    ([applicationID] asc, [changeDate] asc) WITH FILLFACTOR = 90,
CONSTRAINT   [FK_applicationStateChange_application]                             FOREIGN KEY ([applicationID]) REFERENCES [application]([applicationID]))

GO

CREATE NONCLUSTERED INDEX [IX_applicationStateChange_ChangeDate] 
   ON [dbo].[applicationStateChange] ([changeDate] desc)

CREATE NONCLUSTERED INDEX [FI_ASC_ChangeDate] 
   ON [dbo].[applicationStateChange] ([applicationID] desc, [changeDate] asc, [newStatus] asc)
   WHERE ([newStatus]='PLC')
   WITH FILLFACTOR = 100
Run Code Online (Sandbox Code Playgroud)

Mar*_*lli 5

正如我在这个答案中看到的,当我添加option(recompile)到我的查询时,它运行良好,接受索引提示:

SELECT   MAX(AC1.changeDate)   
         -- AC1.changeDate
          FROM [dbo].[applicationStateChange]  AS ac1  WITH(INDEX(FI_ASC_ChangeDate))  
          WHERE AC1.newStatus = 'PLC'  
OPTION (RECOMPILE)
Run Code Online (Sandbox Code Playgroud)

仍然当我运行相同的查询时withoutoption(recompile)我得到相同的错误

消息 8622,级别 16,状态 1,行 479 由于此查询中定义的提示,查询处理器无法生成查询计划。在不指定任何提示且不使用 SET FORCEPLAN 的情况下重新提交查询。

但是,在我的测试环境中,我可以运行以下操作,此后此过滤索引不再有问题:

ALTER DATABASE [JUNOCORE] SET PARAMETERIZATION SIMPLE;
Run Code Online (Sandbox Code Playgroud)

为了证实我在测试中这样做的决定,我阅读了以下文章:

SQL Server 简单和强制参数化

闪电战结果:强制参数化

现在我想将我的[JUNOCORE] databasein LIVE 也改为简单的参数化

这让我想到以下问题:

我应该查看工作负载或查询计划缓存的哪些元素来决定我的数据库中的简单参数化还是强制参数化?