0

Справочная информация: Я бегу на Sql Server 2014 (12.0.2000.8) на лазури ...Невозможно получить хранимую процедуру для изменения индексного сканирования для поиска по индексу

Я нашел удобный скрипт на другой день, который показывает запросы/хранимые процедуры, которые «касаются» индексов. Я искал это некоторое время, потому что у меня есть некоторые индексы, которые выполнялись очень плохо, но я не мог найти, где они были вызваны.

Теперь, когда у меня есть эта информация, я пытаюсь переделать процессы, которые касаются данного индекса.

При просмотре плана выполнения моего запроса он говорит, что делает сканирование, которое, очевидно, не является оптимальным.

Наведение курсора по индексу показывает выходной список соединения, но не предикаты.

Я пошел вперед и создал индекс с точными полями, которые находятся в этом выходном списке.

Вот запрос, который в настоящее время работают:

declare @season int = 2017 

select s.SchoolId, 
     s.Name [SchoolName], 
     s.Conference, 
     tr.DualRank [Rank], 
     convert(varchar(2), tr.DualWins) + ' - ' + convert(varchar(2), tr.DualLosses) [Record], 
     tr.RankingDate, 
     case when tr.WeekNumber = 0 then null 
       else 
        (select trx.DualRank from dbo.TeamRankings trx where trx.Season = tr.Season and trx.WeekNumber = (tr.WeekNumber - 1) and trx.SchoolId = tr.SchoolId) 
        - tr.DualRank 
     end [Trend], 
     (select trx.DualRank from dbo.TeamRankings trx where trx.Season = tr.Season and trx.WeekNumber = (tr.WeekNumber - 1) and trx.SchoolId = tr.SchoolId) [PreviousWeek] 
from dbo.TeamRankings tr 
join dbo.School s on s.SchoolId = tr.SchoolId 
where tr.Season = @season 
and  tr.IsCurrent = 1 
order by tr.DualRank 

только присоединиться к этому списку, который имеет развертку вместо искать является один к столу школы. Он присоединяется к SchoolId, а затем в избранной части выводит имя и конференцию. Кажется довольно прямолинейным.

В моей первой попытке, я пошел вперед и создал свой индекс так:

create nonclustered index idx_NC_School_SchoolId_incs on dbo.School (SchoolId asc) include (Name, Conference) 

но до сих пор в результате сканирования. Моя вторая попытка была сделать это следующим образом:

create nonclustered index idx_NC_School_SchoolId_Name_Conference on dbo.School (SchoolId asc, Name asc, Conference asc) 

Но это все еще делает сканирование во время использования индекса, который я создал.

Что еще я должен искать, чтобы попытаться получить этот запрос для поиска вместо сканирования.

Для получения дополнительной вводной информации, здесь подмножество определения таблицы:

dbo.School 
SchoolId int identity(1,1) primary key, 
Name varchar(100) not null, 
Conference varchar(100) not null -- will soon change this to a lookup table 
...... 

Я знаю, что кто-то спросит, но я не могу понять, как это сделать; как мне приложить свой план выполнения к вопросу?

Вот ссылка на страницу, где данные отображаются: http://www.wrestlestat.com/rankings/dual/live

+0

Общее количество строк в таблице: –

+0

Просто потому, что существует действующий индекс, не всегда означает, что вы получите поиск. Когда-то сканирование отлично, особенно в этом случае, когда я предполагаю, что большая часть строк в Школе возвращается. –

+0

@ Общие школы M.Hassan = 597. Школы, которые возвращаются в этом запросе = 77. – ganders

ответ

0

индекс сканирования не всегда плохо, особенно когда у вас есть очень маленький столик.

Но что-то, что определенно может улучшить производительность вашего запроса, чтобы переместить эти sub-queries из вашего пункта select в from и использовать join.

Что-то вроде ......

declare @season int = 2017 

select s.SchoolId, 
     s.Name [SchoolName], 
     s.Conference, 
     tr.DualRank [Rank], 
     convert(varchar(2), tr.DualWins) + ' - ' + convert(varchar(2), tr.DualLosses) [Record], 
     tr.RankingDate, 
     CASE WHEN tr.WeekNumber = 0 then null 
      ELSE trx.DualRank - tr.DualRank end [Trend], 
     trx.DualRank [PreviousWeek] 
from dbo.TeamRankings tr 
Inner join dbo.School  s on s.SchoolId = tr.SchoolId 

Left join dbo.TeamRankings trx ON trx.Season = tr.Season 
           and trx.WeekNumber = (tr.WeekNumber - 1) 
           and trx.SchoolId = tr.SchoolId 
where tr.Season = @season 
and  tr.IsCurrent = 1 
order by tr.DualRank 

Если у вас есть в предложении select в sub-query, то sub-query выполняется для каждой строки, возвращаемой outer query, если вы переместите его в from пункта и использование соединений, будет executed once и множество результат будет соединенный с результирующим набором, поступающим из других объединений. Гораздо эффективнее и чище.

+0

Я на самом деле сделал это, пока я играл ... – ganders

+0

@ganders, даже если это не дает вам поиска, это, безусловно, лучший вариант, придерживайтесь его. –

0

Вы можете использовать функции окна, такие как LAG и LEAD, чтобы обойти самосоединение с таблицей. Это может привести к более простым планам выполнения.

declare @season int = 2017 

select 
    s.SchoolId, 
    s.Name [SchoolName], 
    s.Conference, 
    tr.DualRank [Rank], 
    convert(varchar(2), tr.DualWins) + ' - ' + convert(varchar(2), tr.DualLosses) [Record], 
    tr.RankingDate, 
    CASE WHEN tr.WeekNumber = 0 THEN NULL ELSE tr.DualRank - LAG(tr.DualRank,1,0) OVER(Partition BY tr.Season,tr.SchoolId ORDER BY trx.WeekNumber) END AS [Trend], 
    LAG(tr.DualRank,1,0) OVER(Partition BY tr.Season,tr.SchoolId ORDER BY trx.WeekNumber) AS [PreviousWeek] 

from  
    dbo.TeamRankings tr 
     join dbo.School s on s.SchoolId = tr.SchoolId 
where 
    tr.Season = @season 
    and  
    tr.IsCurrent = 1 
order by 
    tr.DualRank 

При использовании

trx.WeekNumber = (tr.WeekNumber - 1) 

Вы изменяющий значение tr.WeekNumber, следовательно, отличается от значения, хранящегося в индексе, поэтому SQL выполнит сканирование вместо того, чтобы искать.