2011-12-19 52 views
5

我有Log和LogItem表;我正在編寫一個查詢來從兩者中獲取一些數據。有成千上萬的Logs每個Log最多可以有125 LogItems當現有索引包含新索引中的所有列時,爲什麼創建此新索引會提高性能?

查詢有問題是複雜的,所以我跳過它(如果有人認爲這是重要的我也許可以將它張貼),但是當我跑SSMS估計的查詢計劃,它告訴我一個新的非聚集索引可以將性能提高到100%。

Existing Index: Non-clustered 
Key Colums (LogItem): ParentLogID, DateModified, Name, DatabaseModified 

Query Plan Recommendation 
CREATE NONCLUSTERED INDEX [LogReportIndex] 
ON [dbo].[LogItem] ([ParentLogID],[DatabaseModified]) 

只是爲了好玩,我創造了這個新的指標和運行查詢和出乎我的意料,現在只需約1秒我的查詢運行時之前是10+秒。

我認爲我現有的索引會覆蓋這個新的查詢,所以我的問題是爲什麼在我的新查詢中使用的唯一列上創建新索引可以提高性能?我應該爲我的where子句中使用的每列唯一組合索引有索引嗎?

注意:我不認爲這是因爲SQL Server緩存了我的結果,我在創建索引之前運行了大約25-30次的查詢,並且它在索引之後持續了10-15秒現在一直是〜1或更少。

+0

在創建附加非聚集索引之前,*實際執行計劃*顯示的索引用法是什麼? – 2011-12-19 18:14:24

+0

什麼是提高100%的性能? – JeffO 2011-12-19 18:16:23

+0

@Shark好問題,我不確定。這是我第一次進行性能調試。我一定會抓住這一點。它所說的只是'缺少索引',它說了哪些字段。 – Nate 2011-12-19 18:19:09

回答

6

索引中列的順序很重要。如果過濾需要來自索引的第1列和第4列,則索引不會起作用。只有在前N個連續列進行過濾時纔有用。

這是因爲索引是一棵樹。您無法高效選擇樹的所有節點,因爲它們分散在所有其他地方,屬於不同的值column1column2。但是如果你知道column1column2,在樹中定位正確的分支是不容易的。

+0

那麼假設(一般情況下)是否可以安全地使用一組索引來指向哪個表? – Nate 2011-12-19 18:16:54

+0

我曾經通過確保按照正確的順序使用索引來加強別人的查詢。 – 2011-12-19 18:17:33

+0

@Nate寬泛地說,是的。有些地方可能會重疊,所以你可能有一個很好地覆蓋幾個「where」的索引;或者你可以忽略where子句的某個部分,因爲對某一列的索引不會有幫助(低選擇性);但寬泛地說,是的。 – GSerg 2011-12-19 18:19:52

2

指數的前沿是重要的。

只要您的查詢被索引的前沿「覆蓋」,它就會高效。數據庫索引通常以B樹的形式實現,並且B樹的結構指示搜索必須以特定順序完成,這就是爲什麼組合索引中的字段順序很重要。

如果您有「漏洞」,例如如果您在​​和DatabaseModified上進行搜索,但只有{ParentLogID, DateModified, Name, DatabaseModified}上的索引,則只能有效利用索引的部分索引。

(注:有些的DBMS可以利用通過「跳躍掃描」的{DatabaseModified}部分,但即使你的DBMS做,它比普通索引訪問效率要低得多)

+0

所以,如果我有'列(a,b,c,d,e,f)'和大多數查詢是'...哪裏有(...)和B = 3'我的索引'索引(a,b,c,d)'這是一個很好的,但它沒有幫助,如果我有'...在哪裏(...)和D = 5'這是爲什麼我的新索引「索引(a,d)」提高了性能,對吧? – Nate 2011-12-19 18:42:19

+1

@Nate - 正確。把它想象成電話簿。如果你只知道某人的名字,那就不可能在沒有查看整本書的情況下找到它,因爲它是按姓氏,名字組織的 – JNK 2011-12-19 18:50:59

相關問題