壞索引的定義是什麼?我們如何決定?我們應該有什麼邏輯?
網上有查詢發現壞索引
他們的邏輯很簡單
如果寫入計數 > 讀取計數 = 錯誤索引
這是一個範例查詢
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 以獲得百分比。**注意:**這始終不適用,我將其用作“決勝局”。
- 如果百分比 > 60,您可以保留該索引
- 如果百分比在 50 到 60 之間,您需要自己弄清楚這個指數是否有用。
- 如果它小於 50,則索引在更新中導致的 I/O 使用率比它在加快查詢速度方面的幫助多。
- 如果它在 20-30% 左右,您可以先禁用然後刪除。
例子:
看
index b
它完全不可用。首先禁用它然後將其刪除是正確的決定。看
index a
索引是既讀又更新,但更新多於讀。除法值是 0.80,幾乎是 80%。你可以保持這個索引被使用和更新,我沒有看到這個索引有問題。查看
index C
除法給出 0.33 的值,百分比為 33 %。必須再次調查該指數,這弊大於利。關於百分比的整個想法是基於您對數據庫的了解程度。保留或刪除索引的決定應主要基於需求。它的索引很有可能每兩週或每週使用一次,但每天都會更新。這可能是因為作業每週或每兩週執行一次,並且僅在那時使用這些索引。
此外,您不必擔心頁數 < 2000 的小索引,這又是一個大概的數字,這樣的索引不會造成任何傷害。