運維腳本:索引統計

来源:http://www.cnblogs.com/ljhdo/archive/2017/06/27/4491911.html
-Advertisement-
Play Games

資料庫引擎是高度優化的閉環系統,基於執行計劃的反饋,查詢優化器在一定程度上自動優化現有的執行計劃。查詢優化的核心是索引優化,資料庫引擎通過計數器統計關於索引操作的數據,統計的信息包括:使用次數、物理存儲、底層操作的計數,以及缺失索引等,這些統計數據存儲在記憶體中,是資料庫引擎執行情況的真實反饋,高度概 ...


資料庫引擎是高度優化的閉環系統,基於執行計劃的反饋,查詢優化器在一定程度上自動優化現有的執行計劃。查詢優化的核心是索引優化,資料庫引擎通過計數器統計關於索引操作的數據,統計的信息包括:使用次數、物理存儲、底層操作的計數,以及缺失索引等,這些統計數據存儲在記憶體中,是資料庫引擎執行情況的真實反饋,高度概括了索引的執行情況,有意識地利用索引的統計信息,有針對性地優化現有的業務邏輯代碼,調整查詢的執行計劃,能夠提高資料庫的查詢性能。

一,統計索引的使用次數

在用戶成功提交查詢語句時,執行計劃中每一個單獨的索引操作(Seek,Scan,Lookup或Update)都會被統計到sys.dm_db_index_usage_stats 中,例如,user_updates 計數器統計索引執行Insert,Update或Delete操作的次數,查找計數器(user_seeks, user_scans, user_lookups)統計在索引上執行的seek,scan和lookup操作的次數,如果查找計數器遠遠小於user_updates 計數器,這說明基礎表會執行大量的更新操作,維護索引更新的開銷比較大,資料庫引擎利用索引提升查詢性能的空間有限。 

在計數時,每一個單獨的seek、scan、lookup或update操作都被計算為對該索引的一次使用,並使該視圖中的相應計數器加1。

索引的Seek,Scan,Lookup和Update的含義是:

  • Seek是Index Seek:通過該索引進行查找的次數
  • Scan是Index Scan:通過該索引執行掃描查找的次數
  • Lookup是Key Lookup:通過該索引查找到數據後,再到源數據表進行鍵值查找的次數,Key Lookup是非聚集索引特有的,查詢性能低下,應避免這種查找方法;
  • Update是Index Update:由於源表數據更新導致索引頁更新的次數

Index Seek和Index Scan的區別是:

  • Index Seek是從BTree的根節點開始,向子節點查找,直到葉子節點;
  • Index Scan是在Index的葉子節點上,從左到右,把整個BTree的葉子節點遍歷一遍,類似於Table Scan。

如果索引的Seek,Scan,Lookup的計數值較多,那麼說明索引被引用的次數多;如果查找計數器數值較小,但是Update數值較多,說明維護Index的開銷高於查詢帶來的性能提升,應該考慮修改索引的結構,或者直接把索引刪除。

select db_name(us.database_id) as db_name
    ,object_schema_name(us.object_id)+'.'+object_name(us.object_id) as table_name
    ,i.name as index_name
    ,i.type_desc as index_type_desc
    ,us.user_seeks
    ,us.user_scans
    ,us.user_lookups
    ,us.user_updates
from sys.dm_db_index_usage_stats us 
inner join sys.indexes i 
    on us.object_id=i.object_id and us.index_id=i.index_id
where us.database_id=db_id()
    --us.database_id=db_id('database_name')
    --and us.object_id=object_id('schema_name.table_name')
order by us.user_seeks desc
View Code

二,統計索引的物理存儲

使用 sys.dm_db_index_physical_stats 函數統計索引的物理存儲,例如,碎片的百分比,數據存儲的集中和分散程度,以及page空間的利用率等:

  • avg_fragmentation_in_percent:索引外部碎片的百分比,值越大,說明索引的邏輯順序和物理順序差異越大,查找性能越低;
  • fragment_count:分段的數量,表示索引數據的集中/分散程度;
  • avg_fragment_size_in_pages:分段的大小
  • avg_page_space_used_in_percent:索引內部碎片的百分比,值越大,說明page空間的利用率越高;

請閱讀《索引碎片的檢測和整理》,以瞭解更多。

三,底層操作的計數

使用 sys.dm_db_index_operational_stats 函數統計底層IO、加鎖(Locking)、Latch和數據訪問模式的計數,通過這些數據,用戶能夠追蹤到查詢請求必須等待多長時間才能完成數據的讀寫、標識索引是否存在IO熱點。

在統計索引的底層操作之前,先瞭解跟數據的物理存儲相關的術語:

  • 幽靈數據(ghost)是指:在索引的葉子節點中,數據行被標記為刪除,但是還沒有從索引結構中物理刪除,幽靈數據只存在於索引的葉子節點中,幽靈數據由後臺進程定期執行物理刪除。
  • 轉發數據(forwarding):需要兩次IO操作才能獲取到指定的數據,轉發操作只發生於堆表(Heap)中;當數據行被更新,導致行的Size增大,以致於該行無法存儲在當前的page中,為了避免相關索引的更新,資料庫引擎會把該數據行轉存到一個新的Page中,併在新舊 Page中分別添加一個Pointer:在原Page中,Pointer指向新Page,該Pointer稱作Forwarder Pointer;在新page中,Pointer指向原Page,稱作Back Pointer。在讀取數據時,資料庫引擎首先從Forwarder Pointer中讀取數據存儲的指針,然後,根據指針到相應的地址空間中讀取真正的數據。
  • 獲取(Fetch)數據:用於從LOB或Row_Overflow的分配單元(Allocation Unit)中取回(Retrive)數據,大欄位數據存儲在特定的LOB或Row_Overflow類型的數據頁中。
  • 剝離(Push Off)數據列:用於統計資料庫引擎把LOB或Row-Overflow數據從原有的In-Row 數據頁剝離的次數。在執行Insert或Update操作之後,數據行的Size增長,不能存儲在當前的Page中,必須把大數據欄位的數據從原來的數據行中分離,存儲在指定的分配單元中,這個過程就是數據列的剝離。
  • 拉回(Pull In)數據行:是Push Off的逆過程,用於統計資料庫引擎把數據從LOB或Row-Overflow數據頁拉入到In-Row數據頁的次數,拉入數據行一般發生在更新數據之後,數據行的Size減小,數據行在釋放存儲空間之後,能夠存儲在In-Row Page中,數據引擎把數據從LOB或Row-Overflow數據頁拉入到In-Row數據頁,這個過程是數據列的拉回。

This (pulled in-row) occurs when an update operation frees up space in a record and provides an opportunity to pull in one or more off-row values from the LOB_DATA or ROW_OVERFLOW_DATA allocation units to the IN_ROW_DATA allocation unit.

以下腳本用於統計索引底層的存儲動作和鎖/Latch的爭用:

select db_name(ops.database_id) as db_name
    ,object_schema_name(ops.object_id)+'.'+object_name(ops.object_id) as table_name
    ,i.name as index_name
    ,ops.partition_number
    ,ops.leaf_insert_count
    ,ops.leaf_delete_count
    ,ops.leaf_update_count
    ,ops.leaf_ghost_count
    ,ops.nonleaf_insert_count
    ,ops.nonleaf_delete_count
    ,ops.nonleaf_update_count
    ,ops.range_scan_count
    ,ops.singleton_lookup_count
    ,ops.forwarded_fetch_count

    ,iif(ops.row_lock_wait_count=0,0,ops.row_lock_wait_in_ms/ops.row_lock_wait_count) as avg_row_lock_wait_ms
    ,iif(ops.page_lock_wait_count=0,0,ops.page_lock_wait_in_ms/ops.page_lock_wait_count) as avg_page_lock_wait_ms
    ,iif(ops.page_latch_wait_count=0,0,ops.page_latch_wait_in_ms/ops.page_latch_wait_count) as avg_page_latch_wait_ms
    ,iif(ops.page_io_latch_wait_count=0,0,ops.page_io_latch_wait_in_ms/ops.page_io_latch_wait_count) as avg_page_io_latch_wait_ms
from sys.dm_db_index_operational_stats(db_id(),object_id('dbo.FactThread'),null,null) as ops
inner join sys.indexes i 
    on ops.object_id=i.object_id
        and ops.index_id=i.index_id
order by index_name
View Code

該函數統計的Latch徵用數據主要分為PageLatch和PageIOLatch,其區別是:

  • PageLatch是指:在訪問數據有關的數據頁(Data Page或Index Page)時,如果相應的Page已經存在於Buffer Pool中,那麼SQL Server先獲取buffer的latch,這個Latch就是 PageLatch,然後讀取Buffer中的數據。

    PageLatch是施加在Buffer上的Latch, 用來保護:Data page,Index Page, 系統page(PFS,GAM,SGAM,IAM等)的爭用訪問;在數據更新時,分配新的page,或拆分 索引頁(Index Page),會產生PageLatch 等待。

  • PageIOLatch是指:用於把數據從索引或Heap中載入到記憶體。當數據頁從物理文件中的Page中讀取到記憶體時,申請對記憶體Buffer施加的Latch是PageIOLatch。當數據頁不在記憶體里時,SQL Server 先在記憶體中預留一個Page,然後從硬碟讀取,載入到記憶體Buffer中,此時,SQL Server申請並獲取的latch類型是PAGEIOLATCH,PageIOLatch表示正在進行IO操作。PageIOLatch_EX表示正在將disk中的數據頁載入到記憶體,PageIOLatch_SH表示在載入數據頁到記憶體期間,試圖讀取記憶體中的數據頁,此時載入數據頁的過程沒有完成,處於Loading狀態。如果經常出現PageIOLatch_SH,表明Loading數據頁的時間太長,可能出現IO bottleneck。

分析查詢結果,根據計數器的數值,調整資料庫,使系統達到最優狀態:

  • 如果發現欄位leaf_ghost_count的數值特別大,說明索引中存儲很多幽靈數據,可以通過重建索引(Rebuild)清理幽靈數據行:
alter index index_name
on table_name
rebuild
  • 如果PageIOLatch等待較多,說明資料庫頻繁的執行硬碟IO操作,可能的原因是記憶體不足,或者數據文件沒有分散到多個物理硬碟上
  • 如果PageLatch等待較多,說明資料庫存在IO熱點,可以通過增加數據文件ndf,把資料庫分散到不同的物理硬碟上,以減少IO熱點

四,缺失索引

查詢優化器(Query Optimizer)在執行查詢時,如果檢測到執行計劃缺失索引,會把缺失索引的相關信息存儲在緩存中,通過  sys.dm_db_missing_index_details 可以檢測查詢優化器建議創建的缺失索引。

該視圖返回的缺失索引的索引鍵及包含列信息,在索引列的順序上,相等列(equality)應該排在不等列(inequality)之前,包含列(Included)應該添加到INCLUDE子句中,但是,該視圖不會標識出相等列(equality)的排列順序,需要根據查詢語句和選擇性來設置,索引鍵的第一列至關重要。

select mid.index_handle
    ,db_name(mid.database_id) as db_name
    ,mid.object_id
    ,object_name(mid.object_id) as object_name
    ,mid.equality_columns
    ,mid.included_columns
    ,mid.included_columns
    ,mid.statement
    ,mic.column_id
    ,mic.column_name
    ,column_usage
from sys.dm_db_missing_index_details as mid
cross apply sys.dm_db_missing_index_columns(mid.index_handle) as mic
order by mid.object_id
View Code

 

參考文檔:

An in-depth look at Ghost Records in SQL Server

Index Related Dynamic Management Views and Functions (Transact-SQL)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一,代碼。 二,輸出。 ...
  • 項目用到的地圖功能有點多,同時集成了地圖、定位以及導航這幾個功能。 每個單獨使用,都很順利,但合在一起用會有問題。 我每次集成百度地圖,都會在http://lbsyun.baidu.com/sdk/download?selected=mapsdk_basicmap,mapsdk_searchfunc ...
  • Android表情開發 效果圖: 源碼下載-github:https://github.com/SiberiaDante/EmotionApp (覺得有用的給個星星,支持一下哦) ...
  • 自定義樣式 dialog,可設置界面外點擊屏幕外和返回鍵 是否消失 基本用法如下: Utils 工具類封裝: 效果圖: git 源碼下載 To get a Git project into your build: To get a Git project into your build: To ge ...
  • 由於經常會出現 Schema hasn't been registered for model "User" 這樣的問題,所以深入的尋找了一下原因,一點一點的向上查找,最後解決了。 首先是app.js裡面在使用之前要定義,和初始化註冊一次mongoose() 如圖: 因為下麵的index和users ...
  • 神經網路(neural network)是深度學習中一種非常重要的模型,關於神經網路更詳細的介紹呢,這裡就不介紹了,可以自行搜索瞭解。文章主要整理了7個神經網路的實戰項目,相信對神經網路學習者會有所幫助~ ...
  • 記錄一次生產庫遇到的4031錯誤,後來通過調整sga大小將問題解決了 報錯信息: ORA-04031: 無法分配 32 位元組的共用記憶體 ("shared pool","select user#,password,datats...","SQLA","tmp")Incident details in: ...
  • 問題描述: Hbase master起不來,hdfs沒有問題,起來後沒過一會進程又宕了,hdfs磁碟爆了。 解決過程: 開始懷疑是zookeepr宕了。查看配置發現是zookeeper在三台slaves上面,可能會造成資源搶占,zookeeper會被hbase擠掉。 所以將其中一臺slaves轉到m ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...