2011-09-14 77 views
2

我發現下面的SQL旨在幫助識別缺失的索引。我想更好地理解輸出。DMV找到缺失的索引

SELECT migs.avg_total_user_cost * (migs.avg_user_impact/100.0) * (migs.user_seeks + migs.user_scans) AS ExpectedImprovement 
      , DB_NAME(mid.database_id)   AS DBName 
      , mid.[object_id]      AS ObjectID 
      , mid.statement      AS FullyQualifiedObjectName 
      , 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, '') AS IndexColumns 
      , ISNULL (mid.included_columns, '') AS IncludeColumns 
      , migs.user_seeks 
      , migs.user_scans 
      , migs.last_user_seek 
      , migs.last_user_scan 
     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 

其中一個返回的列是「包含列」。

我想知道這是否意味着所提到的列名應該被添加到索引中的列表中,或者是否有其他功能可以返回那些可能的高訪問列值而不會將它們添加到索引本身。 (也許我想到聽到這樣的功能,或者它可能是另一個供應商的數據庫)

是輸出只是建議索引中列的列表由「包含列」返回值中提到的列擴展?我對輸出做出了反應,表明我爲索引添加了15個字段,這對我來說似乎可能過度。

回答

1

SQLServers允許您「包含」非關鍵列(請參閱詳細信息here)。索引中鍵列和非鍵列之間的主要區別在於非鍵列僅存儲在索引的葉級別中,與存儲在所有級別中的鍵列不同。

我不建議遵循腳本輸出的建議(你的腳本很好,不要誤解我的意思),也就是說,你並不需要創建所有建議的索引幷包含所有列想要你。根據我的經驗,SQLServer希望您使所有查詢具有覆蓋索引,這可能會影響更新/插入的性能並增加數據庫大小。

+0

可以使用SQL Server 2008 R2 SSRMS GUI來指定INCLUDED字段,然後生成腳本?我在GUI中看不到這個選項。檢查生成的SQL是我通常如何學習語法的。 – ChadD

2

非聚集索引既包含索引列的列表,也包含「包含」以供快速引用的列的列表。

例如,假設您有一個包含100列的表格,但您幾乎完全查詢其中的5個表格,預測日期。例如

select col1, col2, col3, col4, YourDate from YourTable where YourDate = '???' 

如果你只收錄日期列,你會做什麼叫做一個rowid查詢(或書籤查找)。您將高效地找到所需的行集,但您需要返回到物理表以獲取要選擇的其他4列(col1-col4)。

如果您使用包含列列表創建索引,那麼這些列恰恰存儲在索引中。

create nonclustered index ix_YourTable on YourTable (
    YourDate) 
include (
    col1, col2, col3, col4) 

現在你不回到表來獲取col1-4,你直接從索引中讀取它們。顯然這增加了該索引所需的存儲量。

你也應該知道,如果你頻繁的查詢變爲

select col1, col2, col3, col4, col5, YourDate from YourTable where YourDate = '???' 

你仍然會使用索引,但你會爲了獲得數據COL5做的RID查找。您需要將col5添加到索引的包含列表中,以便有效地引用它。

希望有幫助!