Sql-Server

壞索引的定義是什麼?我們如何決定?我們應該有什麼邏輯?

  • August 2, 2016

網上有查詢發現壞索引

他們的邏輯很簡單

如果寫入計數 > 讀取計數 = 錯誤索引

這是一個範例查詢

   SELECT  OBJECT_NAME(s.object_id) AS 'Table Name',
       i.name AS 'Index Name',
       i.index_id,
       user_updates AS 'Total Writes',
       user_seeks + user_scans + user_lookups AS 'Total Reads',
       user_updates - ( user_seeks + user_scans + user_lookups ) AS 'Difference'
FROM    sys.dm_db_index_usage_stats AS s WITH ( NOLOCK )
       INNER JOIN sys.indexes AS i WITH ( NOLOCK ) ON s.object_id = i.object_id
                                                      AND i.index_id = s.index_id
WHERE   OBJECTPROPERTY(s.object_id, 'IsUserTable') = 1
       AND s.database_id = DB_ID()
       AND user_updates > ( user_seeks + user_scans + user_lookups )
       AND i.index_id > 1
ORDER BY 'Difference' DESC,
       'Total Writes' DESC,
       'Total Reads' ASC ;
-- Index Read/Write stats for a single table
SELECT  OBJECT_NAME(s.object_id) AS 'TableName',
       i.name AS 'IndexName',
       i.index_id,
       SUM(user_seeks) AS 'User Seeks',
       SUM(user_scans) AS 'User Scans',
       SUM(user_lookups) AS 'User Lookups',
       SUM(user_seeks + user_scans + user_lookups) AS 'Total Reads',
       SUM(user_updates) AS 'Total Writes'
FROM    sys.dm_db_index_usage_stats AS s
       INNER JOIN sys.indexes AS i ON s.object_id = i.object_id
                                      AND i.index_id = s.index_id
WHERE   OBJECTPROPERTY(s.object_id, 'IsUserTable') = 1
       AND s.database_id = DB_ID()
       AND OBJECT_NAME(s.object_id) = 'AccountTransaction'
GROUP BY OBJECT_NAME(s.object_id),
       i.name,
       i.index_id
ORDER BY 'Total Writes' DESC,
       'Total Reads' DESC ;,

然而問題就這麼簡單嗎?我們可以稱所有寫>讀=壞索引嗎?

有沒有更好的邏輯可以定義壞索引的 SQL 查詢?

讓我們忽略確保數據完整性的索引,例如唯一約束

讓我們假設索引每分鐘更新和使用一次

我正在使用 SQL Server 2014,這裡查詢生成的結果

在此處輸入圖像描述

然而問題就這麼簡單嗎?

絕對不。不幸的是,它在應用程序之間可能會有很大差異,因此儘管有許多“經驗法則”,例如您所說的,除了“從未使用過的索引是一種浪費”之外,它們都不是普遍適用的。

我們可以稱所有寫>讀=壞索引嗎?

如果該索引用於強製完整性(即它是唯一索引或支持外鍵),那麼該事實通常會勝過性能要求。此外,寫入可能主要發生在無關緊要的時候(可能是半夜的批量更新),或者這些讀取盡可能快非常重要,因此慢速寫入是值得付出的代價。

在考慮這些問題時,請始終考慮您正在查看的任何數據的時間段。可能是索引本週看起來使用不足,但下周是新報告期的開始,因此使用者正在執行一組不同的操作,並且索引突然看起來更加有用。

永遠不要將經驗法則用作生活中的硬性規則。將它們用作建議,並根據您對特定應用程序需求的了解仔細考慮結果。

您可以擴展您的答案並添加更多詳細資訊嗎?

除非您有更具體的問題,否則必須寫一整本書,這是一個非常廣泛的領域。事實上,很多整本書都是關於這個主題的…… http://use-the-index-luke.com/是一個很好的起點。

沒有絕對的邏輯。用我的話來定義一個好的索引

“如果索引可以加快查詢速度並使其更快,那麼它就是一個很好的索引,您可以保留該索引”。

您有來自 Brent Ozar的 sp_blitzindex,它會指出未使用和錯誤的索引。此外,您還有Jason Strates index Analysis 腳本,它會派上用場。我想以上兩個都會為你完成這項工作。但是,如果您喜歡其他方法,以下是我有時會遵循的方法。

重新分級user reads並且user writes沒有絕對值可以從中確定索引是否被恰當地使用。但我實際上所做的是將使用者讀取除以使用者寫入,然後將其乘以 100 以獲得百分比。

**注意:**這始終不適用,我將其用作“決勝局”。

  1. 如果百分比 > 60,您可以保留該索引
  2. 如果百分比在 50 到 60 之間,您需要自己弄清楚這個指數是否有用。
  3. 如果它小於 50,則索引在更新中導致的 I/O 使用率比它在加快查詢速度方面的幫助多。
  4. 如果它在 20-30% 左右,您可以先禁用然後刪除。

例子:

index b它完全不可用。首先禁用它然後將其刪除是正確的決定。

index a索引是既讀又更新,但更新多於讀。除法值是 0.80,幾乎是 80%。你可以保持這個索引被使用和更新,我沒有看到這個索引有問題。

查看index C除法給出 0.33 的值,百分比為 33 %。必須再次調查該指數,這弊大於利。

關於百分比的整個想法是基於您對數據庫的了解程度。保留或刪除索引的決定應主要基於需求。它的索引很有可能每兩週或每週使用一次,但每天都會更新。這可能是因為作業每週或每兩週執行一次,並且僅在那時使用這些索引。

此外,您不必擔心頁數 < 2000 的小索引,這又是一個大概的數字,這樣的索引不會造成任何傷害。

引用自:https://dba.stackexchange.com/questions/145508