我有一张桌子,上面有nonclustered index
一张桌子datetime2
。
在同一张表上,我有一个字段(char[1])
用于逻辑删除记录,并且可以有 2 个不同的值:(A
活动)或D
(已删除)。
datetime2
字段设置为的记录有 451047 条,NULL
但标记为 的只有 7095条A
。
应用程序中的每个查询仅查找活动记录,因此,NULLs
在日期时间字段中查找的每个查询都得到了非常糟糕的估计,因此执行计划也很糟糕。
看起来我仍然得到旧的估计,即使查询正确使用了过滤索引。有谁知道这种行为的原因?
表定义:
CREATE TABLE [TYDATPRD].[HAND00F](
[STDRECSTS] [char](1) NULL,
[HDHAND] [numeric](14, 0) IDENTITY(1,1) NOT NULL,
[HDCHKINDT] [datetime2](7) NULL,
--lots of other columns which I don't think are needed
CONSTRAINT [PK_TYDATPRD_HAND00F] PRIMARY KEY CLUSTERED (
[HDHAND] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [DATA]
) ON [DATA]
非聚集过滤索引定义:
CREATE NONCLUSTERED INDEX [IX_HAND00F_HDCHKINDT] ON [TYDATPRD].[HAND00F] (
[HDCHKINDT] ASC
)
WHERE [STDRECSTS]='A'
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [INDEXES]
GO
这不直观,但请尝试将
char[1]
列添加到过滤索引定义中:在我的测试中,这导致了正确的估计。
顺便说一句,我注意到你问题中的计划是不同的——一个被适当地参数化,另一个有一个常数。要非常小心如何使用局部变量和类型化常量进行局部测试,尤其是在现实世界中这将通过存储过程的参数来完成时。
另外,要非常小心大小写 - where 子句中的文字 like
= 'a'
and= 'A'
将生成不同的计划,如果它们没有被参数化,因为查询文本是不同的。不要介意在某些归类中它们不会产生相同的结果。(那一char(1)
栏需要允许NULL
吗?)