0

背景:我在Azure上的SQL服務器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 total schools = 597.在此查詢中返回的學校= 77. – ganders

回答

0

索引掃描並不總是一件壞事,特別是當你有一個非常小桌子。

但東西絕對可以提高查詢性能是這些sub-queriesselect從句移至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將進行掃描,而不是尋求。