2012-01-03 33 views
4

我正在設計一個具有單個表格的數據庫,用於需要實施解決方案的特殊場景。表格在短時間後將有數億行,但每行都會相當緊湊。即使有很多行,我也需要插入,更新和選擇速度,以便更好,更快速,因此我需要爲作業選擇最佳索引。SQL Server索引 - 非常大的表,where子句針對的是一個非常小的值範圍 - 我需要where子句的索引嗎?

我的表看起來像這樣:

create table dbo.Domain 
(
    Name varchar(255) not null, 
    MetricType smallint not null, -- very small range of values, maybe 10-20 at most 
    Priority smallint not null, -- extremely small range of values, generally 1-4 
    DateToProcess datetime not null, 
    DateProcessed datetime null, 

    primary key(Name, MetricType) 
); 

選擇查詢將是這樣的:

select Name from Domain 
where MetricType = @metricType 
    and DateProcessed is null 
    and DateToProcess < GETUTCDATE() 
order by Priority desc, DateToProcess asc 

第一種類型的更新將是這樣的:

merge into Domain as target 
using @myTablePrm as source 
on source.Name = target.Name 
    and source.MetricType = target.MetricType 
when matched then 
    update set 
     DateToProcess = source.DateToProcess, 
     Priority = source.Priority, 
     DateProcessed = case -- set to null if DateToProcess is in the future 
      when DateToProcess < DateProcessed then DateProcessed 
      else null end 
when not matched then 
    insert (Name, MetricType, Priority, DateToProcess) 
    values (source.Name, source.MetricType, source.Priority, source.DateToProcess); 

的第二種類型的更新將如下所示:

update Domain 
set DateProcessed = source.DateProcessed 
from @myTablePrm source 
where Name = source.Name and MetricType = @metricType 

這些是最佳插入,更新和選擇速度的最佳索引嗎?

-- for the order by clause in the select query 
create index IX_Domain_PriorityQueue 
    on Domain(Priority desc, DateToProcess asc) 
    where DateProcessed is null; 

-- for the where clause in the select query 
create index IX_Domain_MetricType 
    on Domain(MetricType asc); 

回答

4

觀察:

  • 你的更新應該使用PK
  • 爲什麼不使用TINYINT(取值範圍爲0-255),使行更窄?
  • 你需要日期嗎?你可以使用smalledatetime嗎?

思路:

  • 你的SELECT查詢沒有一個索引來覆蓋它。你需要一個在(DateToProcess, MetricType, Priority DESC) INCLUDE (Name) WHERE DateProcessed IS NULL `:你必須與鍵列,以獲得最好的一個

  • 你可能程度指數有每一個MetricType篩選索引太(保持DateProcessed IS NULL過濾器)進行試驗。另一個之後我會做到這一點時,我有幾百萬行的測試與

+0

啊我不知道包含條款,歡呼聲。 – 2012-01-03 16:34:55

+0

@NathanRidley:我更新了我的答案。 – gbn 2012-01-03 16:38:35

+0

啊,這是一個好主意。你認爲這會造成嚴重的重大差異嗎?第一次運行可能會在數據庫中保留大約1.5億行,這是值得的。 – 2012-01-03 16:42:31

1

我懷疑你最好的性能來自其上PriorityMetricType沒有索引。基數可能太低,因爲這些指數非常不錯。

DateToProcess上的索引幾乎肯定會有所幫助,因爲在該列中只有很大的基數,並且它在WHEREORDER BY子句中使用。我會從第一個開始。

DateProcessed上的索引是否有用可供討論。這取決於您對此專欄預期的NULL值的百分比。像往常一樣,最好的辦法是用一些真實的數據來檢查查詢計劃。

+0

所以你認爲我的第一個索引應該只是在DateToProcess而忽略優先級?我會雖然這將導致指數按照我想要的順序預先安排,這將使sql服務器更少的工作要做? – 2012-01-03 16:27:43

0

在表模式部分,您已經突出顯示「MetricType」是兩個主鍵之一,因此應該將其與名稱列一起編入索引。至於'Priority'和'DateToProcess'字段,因爲這些字段將出現在where子句中,所以它們也不會受到索引,但我不建議您在'DateProcessed'索引的where子句爲null ,只索引一組數據不是一個好主意,請將其刪除並索引整個這兩列。

+0

索引上的where子句將阻止索引值爲expli citly從相關查詢中排除,這將保持索引大小下降並使掃描和更新速度更快。 – 2012-01-03 16:25:58

+0

未來是否需要一個'DateProcessed'不爲空的查詢,我只是在想未來,如果不是這樣就沒關係 – 2012-01-03 16:28:08

+0

不,這個表專門用於在一個非常大的數據集上協助批處理優先級數據的。查詢規則已經非常有用了,如果它們在任何時候都會改變,那麼表格實際上可能會被吹走並仍然從主數據源重建。 – 2012-01-03 16:30:26

相關問題