2009-12-23 51 views
3

我知道如何使用索引(clustured和非clustured) 但是,當我應該在我的表中使用非clustured索引。 應該有什麼樣的場景,以便使我的列無法顯示索引。 我已經通過msdn的指導,但仍有點混亂。定義索引:哪些列和性能會影響?

我應該只做唯一的列作爲NC或應該有任何其他列也作爲NC。

如果我用NC指數超載我的表,那麼它會降低我的表現嗎?

我應該在外鍵列上使用複合非C索引嗎?

我知道主鍵應該是Clustured,唯一鍵應該是NC,但外鍵是什麼。

+0

已編輯問題,已添加2條更多信息 – 2009-12-23 18:20:41

回答

4

您每個表只能有一個聚簇索引。它不一定是主要關鍵,但在大多數情況下會是。

除此之外 - 它確實取決於查詢& tipping point for what indexes will be used。但是定義索引也意味着會對DML產生影響 - 插入,刪除更新會稍微影響性能。

我應該在外鍵的列上使用複合非聚集索引嗎?

列的內容無關緊要,優化器決定使用哪種索引,集羣或其他方式的用法很重要。

2

是的,你可以用太多的索引來重載你的表。一般來說,每個額外的索引都會在索引維護方面花費性能時間。大量更新的表通常應該具有較少的索引。

另一個廣泛的規則(來自Richard Campbell,在RunAs Radio和DotNetRocks上)是,一些寬泛的索引會比大量的窄索引表現更好。廣泛的索引將涵蓋更廣泛的查詢,查詢優化器調查的次數更少。請記住,查詢優化器的運行時間有限。

調查SQL Server事件探查器。那裏有工具(以前是獨立的,但它們已經改變了,我最近沒有用過它們)。他們可以分析工作量並制定索引建議。這些將是比「直觀地選擇」的指標更好的選擇。

0

如果您的查詢引用了不在索引中的列,那麼SQL Server引擎將不得不執行表查找以從實際表中獲取不包含的列。

如果您經常運行這些查詢,則應通過在索引中包含所有引用列來創建「覆蓋」查詢的非聚簇索引。這應該包括任何非唯一的列。

向表中添加索引會降低寫入性能,因爲每次更新表時索引都必須更新。

0

你在做什麼字段查找?搜索?等等。 確定您在運行查詢時使用的字段(WHERE子句) 並且它們可能是很好的候選人。

例如,想一想圖書館。圖書目錄有一個用於ISBN編號的聚集索引和一個用於出版年的非聚集索引等等。

另外,Bart Duncan發表很久以前發佈的東西。 他值得讚揚。

該文章的標題是「您使用SQL的缺失索引DMV嗎?」。查詢並運行此查詢:

SELECT 

    migs.avg_total_user_cost * (migs.avg_user_impact/100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure, 

    'CREATE INDEX [missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle) 

    + '_' + LEFT (PARSENAME(mid.statement, 1), 32) + ']' 

    + ' ON ' + mid.statement 

    + ' (' + ISNULL (mid.equality_columns,'') 

    + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END 

    + ISNULL (mid.inequality_columns, '') 

    + ')' 

    + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement, 

    migs.*, mid.database_id, mid.[object_id] 

FROM sys.dm_db_missing_index_groups mig 

INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle 

INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle 

WHERE migs.avg_total_user_cost * (migs.avg_user_impact/100.0) * (migs.user_seeks + migs.user_scans) > 10 

ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC 

這不是您的最終解決方案,但它會幫助您確定一些索引。 並鏈接到文章:http://blogs.msdn.com/bartd/archive/2007/07/19/are-you-using-sql-s-missing-index-dmvs.aspx。默認情況下,當你在SQL Server中創建一個PK時,默認情況下它是聚簇索引,它不一定是,但通常是。

8

集羣索引定義了您的表的物理結構(某種程度上) - 例如,它定義了數據排序的順序。想想電話簿,它由(姓氏,名字)「聚集」 - 至少在大多數國家是這樣。

您每個表只能獲得一個聚簇索引 - 所以明智地選擇它!根據Queen of Indexing, Kimberly Tripp的福音,聚類關鍵應該是狹窄的,穩定的(永不改變),獨特的(是!),並且理想的是不斷增加。

它應該很窄,因爲集羣密鑰將被添加到每個非聚集索引的每個條目 - 畢竟,集羣密鑰是用於最終找到實際數據的值。

它應該是穩定的,因爲不斷更新大量的索引值是一件昂貴的事情 - 尤其是因爲聚簇鍵也必須在所有非聚集索引中更新。

它需要是唯一的,因爲它再次 - 它最終是用於定位實際數據的值。如果你選擇一個不保證是唯一的列,SQL Server將通過向它添加一個4字節值來「分離」你的集羣密鑰 - 這不是一件好事。

理想情況下,羣集密鑰應該不斷增加,因爲這會導致最少的頁面和索引碎片,因此最適合於性能。

羣集鍵的理想候選人將是一個INT(或BIGINT)身份 - 它理想地滿足所有這些要求。

至於非聚集索引 - 使用和明智地選擇它們!我只能給出一條通用規則:屬於外鍵(引用另一個表)的所有列應該位於索引中 - SQL Server不會(與流行的觀點和大量的神話相反)將這樣的索引放置到位自動 - 永遠不會,永遠不會。

除此之外 - 你需要關注你的系統,看看你有什麼樣的查詢 - 所有列出現在WHERE或SORT子句中的列都是可能被索引的列 - 但是太多索引不是好東西事情要麼....

+1

希望我可以多次投票。很好的答案! – 2009-12-23 19:10:56

+0

@CylonCat:非常感謝!很高興它對某人 – 2009-12-23 19:26:02

+0

+1非常有用,可以解釋很多問題。沒有接受bcoz OMG Ponies提供了一個非常好的鏈接,以便更多地瞭解非Clustured指數 – 2009-12-23 19:30:23

0

如果您還是不使聚簇索引取決於你的工作量(通常通過點擊表格中的數量和種類的SELECT語句爲主)

可根據聚簇索引將強制行的磁盤存儲以到聚集索引值。 (因爲這個原因,每個表只能有一個聚簇索引,因爲行只存儲在磁盤上一次)如果大多數查詢總是要求一組相關的行,那麼這很有意義。

示例:假設您正在存儲CustomerOrders,並且您經常想知道某個時間段內CustomerOrder的數量(不管客戶)。在這種情況下,創建一個OrderDate作爲第一列的羣集索引可能很有用。另一方面,如果您經常使用相同的CustomerId查找所有CustomerOr,則將CustomerId作爲第一列放入聚簇索引中更有意義。

聚簇索引的缺點不在於聚簇索引本身,而是在二級索引上:二級索引本身沒有聚集(根據定義,因爲行只能存儲一次,並且按聚簇的順序存儲索引),並且它們的索引條目指向聚集索引的索引條目。因此,通過二級索引檢索一行需要2次讀操作:二級索引之一,然後是它指向的聚簇索引之一。

+0

我mrested只在非Clustured指數。我想xpore NCI,因爲他們可以很多 – 2009-12-23 18:29:01