Sql server 带有datepart的索引视图,对datepart的查询未使用索引

Sql server 带有datepart的索引视图,对datepart的查询未使用索引,sql-server,sql-server-2008,tsql,indexed-view,Sql Server,Sql Server 2008,Tsql,Indexed View,我需要通过datepart(day,BornDate)和/或month在一个有几百万行的表上进行查询,这是CPU的目的 我尝试将索引视图与datepart列一起使用,甚至在索引视图本身的datepart(day,BornDate)列上创建非聚集索引。但是执行计划仍然告诉我,查询是使用基础表上的datepart计算的 我运行的查询如下所示: set statistics time on SELECT count(1) FROM [dbo].[DemandsBornDateParts] where

我需要通过
datepart(day,BornDate)
和/或month在一个有几百万行的表上进行查询,这是CPU的目的

我尝试将索引视图与datepart列一起使用,甚至在索引视图本身的
datepart(day,BornDate)
列上创建非聚集索引。但是执行计划仍然告诉我,查询是使用基础表上的
datepart
计算的

我运行的查询如下所示:

set statistics time on
SELECT count(1) FROM [dbo].[DemandsBornDateParts] where borndateday = 5 OPTION (RECOMPILE)
set statistics time off
我总是将其与指向基础表的相同查询进行比较:

set statistics time on
select count(1) from dbo.Demands where DAY(borndate) = 5
set statistics time off
它们都显示几乎相同的查询计划,具有几乎相同的子树成本、CPU和运行时间,都使用谓词
datepart(day、[dbo].[Demands].[BornDate])=(5)执行聚集索引扫描

视图的定义如下:

GO  
--Set the options to support indexed views.  
SET NUMERIC_ROUNDABORT OFF;  
SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT,  
    QUOTED_IDENTIFIER, ANSI_NULLS ON;  
GO  
--Create view with schemabinding.  
IF OBJECT_ID ('dbo.DemandsBornDateParts', 'view') IS NOT NULL  
DROP VIEW dbo.DemandsBornDateParts ;  
GO  
CREATE VIEW dbo.DemandsBornDateParts
WITH SCHEMABINDING  
AS  
    SELECT id,
           Datepart(DAY, borndate)   AS BornDateDay,
           Datepart(MONTH, borndate) AS BornDateMonth,
           Datepart(YEAR, borndate)  AS BornDateYear
    FROM   DBO.demands  
GO  

--Create an index on the view.  
CREATE UNIQUE CLUSTERED INDEX [PK_dbo.DemandsBornDateParts]
    ON dbo.DemandsBornDateParts (Id);  
GO
CREATE NONCLUSTERED INDEX [IX_BornDateDay] ON [dbo].[DemandsBornDateParts]
(
    [BornDateDay] ASC
)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 [PRIMARY]
GO
如何在不反复重新计算
datepart
的情况下使用持久化/索引列?我不能使用持久化列,我需要使用一个视图。

在查询中的视图名称后添加
WITH(NOEXPAND)
。从以下文件:

NOEXPAND

指定在查询优化器处理查询时,不展开任何索引视图以访问基础表。查询优化器将视图视为具有聚集索引的表。NOEXPAND仅适用于索引视图

从同一页上:

要强制优化器对索引视图使用索引,请指定NOEXPAND选项


尝试更新该表的统计信息。这可能是查询计划不考虑索引的一个原因。正如TT发布的文章中所指出的那样,这没有帮助,问题是我们使用standard edition,它一直在扩展,除非强制不要。这很有吸引力,但为什么sql server不隐式使用它呢?问题是,我想将视图映射到EF代码第一个实体。为了方便起见,这必须是一个没有提示的简单查询。@MichalŘehout查询优化器尽了最大努力,但并不总是正确的。我假设从启发式或引擎开发人员(我不是)对查询性能的一些见解来看,默认行为是尝试扩展视图并使用底层表。有时你必须握住发动机的手,告诉它换一种方式。这就是为什么会有这样明确的查询和表提示。谢谢。我将对此进行详细说明,但这是正确的答案。@MichalŘehout您可能会从sqlperformance.com上的这篇文章中获得更多的见解:我认为在EF6中不可能以某种方式轻松完成这项工作,现在我使用的是原始sql查询,当您需要优化性能时,它会更好。