2014-05-24 50 views
0

我發現了一個非常奇怪的行爲,我必須解釋。我們有一個簡單的表格,大約有450.000個條目(MSSQL 2008 R2)。MSSQL:爲什麼這個索引比其他索引快10倍?

此表的索引是很簡單的:

指數#1包含:

[OwnerUserID] -> int, 4 byte 
[TargetQuestionID] -> int, 4 byte 
[LastChange] -> date, 8 byte 

指數#2包含:

[LastChange] is a date, 8 byte 
[OwnerUserID] is an int, 4 byte 
[TargetQuestionID] is an int, 4 byte 

正如你所看到的,所不同的只是列的順序略有不同;在這兩個指標中,葉子的大小相同,16個字節(遠離我見過做的非常大的數據庫,一些DBA的)

的查詢很簡單:

Query #1: 
- Asks just for the last entried element (top(1)) ordered by LastChange, so it takes only LastChange into account 

Query #2: 
- Asks just for the last entried element (top(1)) entried for a distinct OwnerUserID, so it takes OwnerUserID and LastChange into account 

結果是:

指數#1查詢#1超級慢,雖然我認爲這應該是OK,因爲數據葉子是真的不大(16個字節)

指數#2是用於查詢#2超慢(但由於它需要考慮兩個值,OwnerUserID + LastChange = 8個字節,我沒有看到任何爲什麼它應該更慢/更快)

我們的想法是隻有一個索引,但由於每個查詢方案的性能相差10-11倍,我們最終並行創建了這兩個索引的兩個,我們認爲我們可以選擇其中一個 - 因爲這個指數並不是那麼大/複雜,你會認爲這個列順序上的細微差別會受到傷害。

所以,現在我們是在浪費一倍的空間,因爲該表由每天1萬行左右的增長,我們將磁盤空間問題的地方在未來...

起初,我以爲這是因爲一些內部NHibernate的問題,但我們檢查了性能監視器,結果是絕對可重現的。

好像與指標MSSQL性能高度依賴的datetime-列的使用,因爲這個簡單的例子表明,這可能崩潰全性能: -/

+0

檢查執行計劃。 –

+0

嘿嘿,那是真的 - 我們只檢查了SQL分析器,看看它需要多長時間,但不是執行計劃: -/ – johngrinder

回答

2

通常被用於索引來進行快速的二進制搜索可能的,而不是緩慢的順序搜索。爲了達到這個目的,他們按照排序順序或樹形結構存儲索引鍵。但是,只有密鑰的開始是已知的,因此二進制搜索纔是可能的,因此元素的順序很重要。在你的情況下,這意味着:

  • 查詢#1需要具有最低LastChange的記錄。該查詢可以使用以LastChange開頭的索引來優化,例如,排名第2。使用索引#1,它需要回退到順序搜索。
  • 查詢#2需要首先查找所有唯一的OwnerIds,並且以OwnerId開頭的索引可以幫助您。然後它需要爲特定的OwnerId找到最低的LastChange。索引#1在這裏沒有幫助,因爲索引中的下一個字段不是LastChange。如果同一個OwnerId有很多記錄,索引2可能會有所幫助。否則,它可能會進行順序搜索。

因此,對於索引,字段的順序應該與查詢相匹配。此外,您可能需要更新統計信息,以便查詢計劃人員有一個想法,即如果順序搜索更好(每個OwnerId少數條目)或使用索引2(每個OwnerId大量條目)。我不知道是否以及如何用mysql來完成,只能從postgresql知道。

索引總是一個折衷:它會減慢插入速度,但會加速查詢。所以它高度依賴於你的應用程序你有多少指數以及它們將如何構建。

+0

此外:使用您提供的工具,而不是問一個問題。查看查詢計劃 - 他們很樂意向您展示使用哪些索引。管理人員Studi可以很好地監視他們。 – TomTom

+0

TomTom,如上所述:好主意 - 我們沒有檢查的執行計劃,只有SQL Profiler ... – johngrinder

相關問題