2016-11-12 2 views
3

Мне нужно сделать запрос по datepart(day, BornDate) и/или месяцу на таблице с несколькими миллионами строк, которая является vain CPU intenstive.Индексированный просмотр с датой, запрос на datepart не использует индекс

Я попытался использовать индексированный просмотр с столбцами 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 

Они оба показывают практически одинаковые планы запросов, с почти те же затраты на поддерево, процессор и прошедшее время, оба выполняют кластерное сканирование индекса с предикатом 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 снова и снова? Я не могу использовать постоянные столбцы, мне нужно использовать представление.

+0

Попробуйте обновить статистику этой таблицы. Это может быть одной из причин, по которой Query не учитывает ваш индекс. –

+1

Не помогло бы, как указано в статье, опубликованной TT. Дело в том, что мы используем стандартную версию, которая все время разворачивает, не слишком. –

+0

Спасибо за информацию @Michal Řehout –

ответ

3

Добавить WITH(NOEXPAND) после имени вида в запросе. Из документации на Table Hints:

NOEXPAND

Указывает, что любые индексированные представления не расширены, чтобы получить доступ базовые таблицы, когда оптимизатор запросов обрабатывает запрос. Оптимизатор запросов рассматривает представление как таблицу с кластеризованным индексом. NOEXPAND применяется только к индексированным представлениям.

И от Remarks on Using NOEXPAND на той же странице:

Чтобы заставить оптимизатор использовать индекс для индексированного представления, указать опцию NOEXPAND.

+0

Это работает как шарм, но почему сервер sql не использует его неявно? Дело в том, что я хотел бы отобразить представление в EF-кодовую первую сущность. Что, что нужно сделать легко, должно быть простым запросом без каких-либо намеков. –

+0

@ MichalŘehout Оптимизатор запросов делает все возможное, но не всегда правильно. Я предполагаю, что из эвристики или некоторых соображений от разработчиков движка (которых я не являюсь) в отношении производительности запросов поведение по умолчанию заключается в попытке расширить представление и использовать базовые таблицы (таблицы). Иногда вам нужно держать ручку двигателя и говорить ей, чтобы сделать это по-другому. Вот почему такие явные подсказки и таблицы существуют. –

+0

Спасибо. Я подробнее расскажу об этом, но это правильный ответ. –

Смежные вопросы