運行緩慢的查詢語句(監測索引的使用)


  另外一個影響查詢性能的因素跟DML查詢已經刪除,插入以及更改數據的查詢有關。在指定表上創建的索引越多,更改數據時需要占用的資源也就越多。當事務之間存在鎖的組合時,較長的更改操作會破壞並發性。結果,所以,了解哪個索引被應用程序超時使用就顯得很重要。然后你就可以指出是否在數據庫中結構中存在着從未被使用過的索引。

  SQL Server2008提供了sys.dm_db_usage_stats DMV,它顯示出了哪些索引被使用以及它們是在被用戶查詢所使用還是僅僅共系統操作使用。伴隨着查詢的每一次執行,這個動態管理試圖返回的列會隨着查詢語句中使用的執行計划的增加而增加。數據是在SQL Server運行的時候被收集的。這個dmv中數據僅被存儲在內存中,並且不會被永久保存。所以當SQL Server實例停掉以后,數據也會丟失。你可以間歇性地獲取並保存這些信息,便於以后對它們進行分析。

  在索引上的操作被划分為用戶類型及系統類型兩種。用戶類型傾向於SELECT,INSERT,DELETE以及UPDATE操作,或者更新統計信息。兩種類別的語句在列中對比顯示如下:

  • 在索引上的查找(seek)操作 (user_seeks or system_seeks).
  • 在索引上的查閱(Lookup)操作 (user_lookups or system_lookups).
  • 在索引上的遍歷操作(Scan) (user_scans or system_scans).
  • 在索引上的更新(Update)操作 (user_updates or system_updates).

對於這些在索引上的每一種操作,最后的訪問都會被標記上一個時間戳。索引本身通過三個列被識別:database_id,object_id,index_idindex_id=0表示一個堆類型的表,index_id=1表示一個群集索引,index_id>1表示一個非聚集索引。

應用程序在數據庫上持續應用,sys.dm_db_index_usage_stats可訪問的索引列表也會隨之增加。

SQL Server上scan,seek,以及lookup工作的定義及規則如下:

  • Seek:指出訪問數據的過程中B樹結構被使用了多少次。無論B-樹結構是被用來從各層級上讀取幾個頁面進而只獲取一個數據行,還是近乎一半的索引頁被讀取進而從基礎表中讀取幾G的數據。所以你可以期望所有對應索引的查找都落在這個類別里。
  • Scan:指出在數據層不使用B-樹結構去獲取數據時對表的訪問次數。對於未定義任何索引的表,就可能是這種scan的情況。對於表上已經定義了索引的情況,如果查詢未使用創建在表上的任何索引,scan也會發生。
  • Lookup:它表示因非聚集索引指針指向聚集索引而引起的聚集索引對數據的查找。這個場景在SQL Server2000及更在版本中被稱書簽查找(Bookmark lookup)。它呈現了這樣一種場景:一個非聚集索引被用來去訪問某個表,並且這個非聚集索引並沒有涵蓋select查詢中的所有列,並且這個列被定義在了where謂詞中。SQL Server會為非聚集索引增加user_seeks這個列中的值並加上作為聚集索引入口的user_lookups列中的值。如果表上定義了很多的非聚集索引,這個和值會變得很高。如果用戶在表的某一個索引上seek的次數很高,那么用戶lookups的次數也會很高,並且如果用戶對某一個非聚集索引的訪問次數也很高,你就應該考慮讓非聚集索引幫助解決聚集索引高數量使用的問題。

下面的DMV查詢可以被用來去獲取所有數據庫上的所有對象的索引使用信息:

select object_id, index_id, user_seeks, user_scans, user_lookups 
from sys.dm_db_index_usage_stats 
order by object_id, index_id

你可以參考下面的輸出

object_id       index_id    user_seeks    user_scans    user_lookups 
--------------------------------------------------------------------
521690298        1          0             251           123
521690298        2          123           0             0


  當前情況下有251個對應於某一查詢的執行直接訪問數據層中的表,而沒有使用任意一個索引。有123個對應於某一查詢的執行通過第一個非聚集索引訪問表,它既沒有涵蓋Select中的列也沒有涵蓋where謂詞中指定的列,因為我們看到有123個lookup存在於聚集索引之上。

  sys.dm_db_index_usage_stats中最有意思的列是用來查看用戶類型的列,包括user_seeksuser_scans。系統使用列,比如system_seeks可以被認為是已經存在的索引的結果。如果索引不存在,它就可以不必強制更新統計信息並且也可以不需要被檢查一致性。所以,分析工作需要關注那四個列以指出即時查詢及用戶應用程序對索引的使用情況。

  為了獲取指定表在SQL Server最后一次啟動后一直未被使用的索引的信息,可以在擁有這個對象的數據庫中運行下面查詢:

select i.name
from sys.indexes i 
where i.object_id=object_id('<table_name>') and
    i.index_id NOT IN  (select s.index_id 
                        from sys.dm_db_index_usage_stats s 
                        where s.object_id=i.object_id and     
                        i.index_id=s.index_id and
                        database_id = <dbid> )

  所有未被使用過的索引可以通過下面的語句獲取到:

select object_name(object_id), i.name 
from sys.indexes i 
where  i.index_id NOT IN (select s.index_id 
                          from sys.dm_db_index_usage_stats s 
                          where s.object_id=i.object_id and 
                          i.index_id=s.index_id and 
                          database_id = <dbid> )
order by object_name(object_id) asc

  當前的情況,表名及索引名稱按照表名被存儲。

  這個DMV的真實目的是觀察長時間運行的索引的使用情況。可能最好是去創建一個針對視圖的快照或者針對結果的快照並且存儲起來,按照這種方式每天執行一次並且去對比彼此的變化。如果你可以明確識別出哪個索引已經好幾個月或者有段時間都沒有被使用過了,你可以最終從數據庫中刪除掉這些索引。

 

 

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM