2008-10-30 87 views
12

顯然(methinks),在BIT列上創建索引是不必要的。但是,如果您有需要搜索的列,那麼每個值都可能是唯一的,例如BlogPostStreetAddress或其他東西,則索引似乎是合適的(再次,methinks)。何時創建新的SQL Server索引?

但是什麼是臨界值?如果你期望10,000行,你會有大約20個獨特的值。應該創建索引嗎?

在此先感謝。

回答

15

對此的最佳答案是分析您的查詢並查看索引是否改進您的查詢。回答這個問題的困難在於幾乎不可能概括查詢優化器的行爲。這就是說,一個經驗法則是,如果您的選擇性對於某個表上的給定查詢的選擇性爲10%或更低,那麼您很可能會從索引中受益。因此,在您的示例中,如果您的值均勻分佈,可能從受益。但是,考慮到你的桌子很小,所以你的表現提升可能可以忽略不計。

這不是一條硬性規則,因爲有很多因素可以改變10%的數字,包括使用聚集或其他索引類型,行的大小,如果某些列不內聯,查詢結構等。

還要記住,插入帶有索引的表中存在顯着的性能損失。如果此表經常更新或追加,則來自索引的速度提升可能會被較慢的插入和更新所抵消。

請參閱Tablescan vs Index access上的MSDN文章。

編輯:正如其他人指出的,如果您正在執行聚合查詢(例如計算特定值出現的次數),則您的查詢可能從索引中受益。如果您經常在特定列上排序,您可能也會受益。

1

在您建議的列中,將有理由爲數據創建引用或查找表以避免數據冗餘。這將使您的列成爲外鍵,指向新查找表的PK。

應對所有外鍵列進行索引。

否則,我會避免在正常情況下在這樣的列上放置索引。

1

BIT列上創建索引是不必要的。

你會感到驚訝。

我已經像一個查詢創建涉及有點列的索引:

SELECT foo.Name FROM foo WHERE foo.Active = 1 

有此表約有300,000行雖然。

+0

多大比例行確實比其他可能的值活動= 1代表什麼?我懷疑這是整個表格的一個相對較小的子集。 – 2008-10-30 14:33:27

+1

它不起作用。我已經嘗試過並且有MS確認 - 無論比例如何,低基數指數都被忽略。 – dkretz 2008-11-08 23:21:09

2

詹姆斯撞在了頭上。我只是補充一點,即使是一個列可能會從索引中受益,具體取決於您如何使用該表。例如,如果您需要統計一天中有多次的行數,那麼可以使用索引。索引並不總是找到一條記錄 - 它們也可以用於聚合。

0

我想說這一切都取決於如何使用表和整個系統的要求。例如,如果它是大JOIN的一部分,並且父類是一個巨大的報表類型表,那麼您肯定會希望索引。如果它與數據庫中的其他表相比相對較小,並且它被大量插入並且很少被讀取,則索引可能不是期望的。

但是,整個數據庫與可分配資源之間的操作範圍是關鍵的決定因素。這就是這個表格+可能的索引在整個系統中的行爲,而不是你所有的其他表格和他們的需求。如果你不考慮大局,你可以通過試圖應用一些任意的規則來殺死整個系統,只是爲了應用任意規則。

2

基數低的索引是非常有問題的。如果只有幾個可能的值,SQL Server幾乎總是進行索引掃描,無論比例如何。

例如:我有一個表只有接受「A」,「N」和「R」值的State字段(對於Active,New和Retired)。通常情況下,其中95%是「R」,4 +%是「A」,少數是「N」。 SELECT WHERE state ='N'將進行表掃描,無論如何。

但 - 有一種新的索引類型,稱爲Filtered Index,最終處理這種情況。當你想排除具有NULL值的記錄時,它也很方便。

0

如果你開始在查詢中遇到死鎖,你通常應該在SELECT和INSERT/UPDATE之間仔細檢查你的索引。索引選擇不當可能會導致死鎖,因爲根本無法獲得索引。有關其他信息,請參閱this knowledge base文章。通常,添加索引或修改其包含的列將有助於解決此類死鎖問題。一定要檢查受影響的查詢的查詢計劃。

0

的最好辦法之一是使用在SQL Server MVP的觀點我sugest不要重新啓動服務器一個星期,然後再運行此查詢:

USE master; 
Go 
SELECT d.database_id, 
    d.object_id, 
    d.index_handle, 
    d.equality_columns, 
    d.inequality_columns, 
    d.included_columns, 
    d.statement AS fully_qualified_object, 
    gs.* 
FROM sys.dm_db_missing_index_groups g 
JOIN sys.dm_db_missing_index_group_stats gs ON gs.group_handle = g.index_group_handle 
JOIN sys.dm_db_missing_index_details d ON g.index_handle = d.index_handle 

Go 

SELECT mig.index_group_handle, 
    mid.index_handle, 
    migs.avg_total_user_cost AS AvgTotalUserCostThatCouldbeReduced, 
    migs.avg_user_impact AS AvgPercentageBenefit, 
    'CREATE INDEX missing_index_' + CONVERT (varchar, mig.index_group_handle) 
    + '_' + CONVERT (varchar, mid.index_handle) 
    + ' 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 
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 
Order By migs.avg_user_impact Desc 

然後驗證表,並創建requerd指數。

0

已經在這裏發佈了很好的答案...只需添加我的兩分錢....執行失蹤索引DMV並查看您提到的表是否被列爲創建新索引的候選人並查看定義該指數。

Are you using SQL's Missing Index DMVs?

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