SQL SERVER DMO 簡介

一、SQL SERVER DMO 簡介

簡介:

        從SQLServer2005開始,微軟引入了一個名叫DMO(動態管理對象)的新特性,DMO可以分爲DMFsDynamic Manage Functions,動態管理函數)和DMVsDynamic Manage Views,動態管理視圖)兩部分。這些函數和視圖用於查找SQLServer實例內部統計信息以供性能監控所用。它們提供實時的,關於SQLServer內部工作的,能用於性能分析和性能故障排除的各種統計信息。

        所有的DMO都屬於sys架構,並且以dm_開頭。執行DMO需要有VIEW SERVER STATEVIEW DATABASE STATE權限。


下面簡述一下本系列將要介紹的DMO

Ø  執行相關的DMOsys.dm_exec_*):提供與執行相關的統計信息。可以用於監控與緩存查詢、執行計劃、活動連接/會話和帶有執行計劃的當前運行的查詢的相關統計信息。

Ø  索引相關的DMOsys.dm_db_index_*sys.dm_db_missing_*):提供關於索引的統計信息。這些DMO可以用於監控和分析因爲丟失索引、無效索引而導致的性能問題,也可以用來檢查索引的使用情況。

Ø  數據庫相關DMOsys.dm_db_*):提供數據庫相關統計信息。可以用於監控和分析數據庫的性能問題,分析數據庫相關文件的統計信息、會話統計信息和任務統計信息。

Ø  I/O相關DMOsys.dm_io_*):提供I/O操作的統計信息,用於監控和分析SQLServerI/O性能問題。

Ø  OS相關DMOsys.dm_os_*):提供關於sqlos內部統計信息,用於監控和分析服務器配置問題。

Ø  事務相關的DMOsys.dm_trn_*):提供事務相關的統計信息,用於監控和分析長時間運行的事務的鎖定、死鎖問題。

 

這些DMO的數據可以通過DBCC SQLPERF(‘SYS.DM_OS_WAIT_STATS’,CLEAR)或者重啓服務器來重置。

監控當前查詢:

SELECT DB_NAME(R.database_id) AS DatabaseName ,

        S.original_login_name AS LoginName ,

        S.host_name AS ClientMachine ,

        S.program_name AS ApplicationName ,

        R.start_time AS RequestStartTime ,

        ST.text AS SQLQuery ,

        QP.query_plan AS ExecutionPlan ,

        R.cpu_time AS CPUTime ,

        R.total_elapsed_time AS TotalTimeElapsed ,

        R.open_transaction_count AS TotalTransactionOpened ,

        R.reads ,

        R.logical_reads ,

        R.writes AS TotalWrites

FROM sys.dm_exec_requests AS R

        INNER JOIN sys.dm_exec_sessions AS S ON R.session_id = S.session_id

        CROSS APPLY sys.dm_exec_sql_text(R.sql_handle) AS ST

        CROSS APPLY sys.dm_exec_query_plan(R.plan_handle) AS QP

ORDER BY TotalTimeElapsed DESC 

GO


監控當前打開的遊標:

SELECT S.host_name AS ClientMachine ,

        S.program_name AS ApplicationName ,

        S.original_login_name AS LoginName ,

        C.name AS CursorName ,

        C.properties AS CursorOptions ,

        C.creation_time AS CursorCreatinTime ,

        ST.text AS SQLQuery ,

        C.is_open AS IsCursorOpen ,

        C.worker_time / 1000 AS DurationInMiliSeconds ,

        C.reads AS NumberOfReads ,

        C.writes AS NumberOfWrites

FROM sys.dm_exec_cursors (0) AS C

        INNER JOIN sys.dm_exec_sessions AS S ON C.session_id = S.session_id

        CROSS APPLY sys.dm_exec_sql_text(C.sql_handle) AS ST

ORDER BY DurationInMiliSeconds DESC 

GO


分析:

在上面步驟中,使用了以下的DMOs

Ø  Sys.dm_exec_requests

Ø  Sys.dm_exec_sessions

Ø  Sys.dm_exec_sql_text

Ø  Sys.dm_exec_query_plan

 

對於上面的查詢結果,需要思考的問題:

Ø  哪個庫正在接受請求?

Ø  那個登錄名執行了這個請求?

Ø  請求是從哪個計算機發出的?

Ø  請求是從那個應用程序發出的?

Ø  請求是何時到達SQLServer的?

Ø  請求中需要執行什麼SQL語句?

Ø  執行的SQL語句的執行計劃是什麼?

Ø  請求的持續時間有多少?

Ø  請求是否開啓了事務?

Ø  請求造成的讀寫數是多少?

Ø  請求是否被阻塞了?如果是,是哪個會話造成的?

 

        爲了找到這些信息,需要把sys.dm_exec_requestssys.dm_exec_sessionssession_id列關聯。

同時,使用CROSS APPLY來關聯sys.dm_exec_sql_text()函數來查找請求的SQL文本。關聯sys.dm_exec_query_plan()函數來查找請求的執行計劃。這兩個函數需要從查詢中分別獲得sql_handleplan_handle。在結果集中,按TotalTimeElapsed列排序,可以知道最耗資源的查詢。

 

        第二個查詢中使用了sys.dm_exec_cursors()函數來返回當前正在使用的遊標的詳細。這個函數接受session_id作爲參數。如果傳入了特定session_id,只會返回該會話的遊標,如果傳入0,則返回所有會話的遊標。結果集按照DurationInMiliSecondes排序,一邊查找最耗資源的遊標,注意worker_time除以了1000,因爲這個的單位是微妙,除以1000可以得到毫秒。


二、用DMV和DMF監控索引性能         

SQLServer有專門的DMO來顯示索引相關統計信息。能幫助你分析現有索引的性能情況。通過這些DMO,可以做到:

Ø  檢查索引使用模式

Ø  查找丟失索引

Ø  查找無用索引

Ø  查找索引碎片

Ø  分析索引頁分配明細

下面將使用這些DMO來檢查數據庫的丟失索引,索引上的查找和掃描操作,並分析索引碎片是否有必要重組或重建。


查找丟失索引:
SELECT MID.statement AS ObjectName ,
        MID.equality_columns ,
        MID.inequality_columns ,
        MID.included_columns ,
        MIGS.avg_user_impact AS ExpectedPerformanceImprovement ,
        ( MIGS.user_seeks + MIGS.user_scans ) * MIGS.avg_total_user_cost
        * MIGS.avg_user_impact AS PossibleImprovement
FROM sys.dm_db_missing_index_details AS MID
        INNER JOIN sys.dm_db_missing_index_groups AS MIG ON MID.index_handle = MIG.index_handle
        INNER JOIN sys.dm_db_missing_index_group_stats AS MIGS ON MIG.index_group_handle = MIGS.group_handle

GO

索引使用明細:
SELECT O.name AS ObjectName ,
        I.name AS IndexName ,
        IUS.user_seeks ,
        IUS.user_scans ,
        IUS.last_user_seek ,
        IUS.last_user_scan
FROM sys.dm_db_index_usage_stats AS IUS
        INNER JOIN sys.indexes AS I ON IUS.object_id = I.object_id
                                       AND IUS.index_id = I.index_id
        INNER JOIN sys.objects AS O ON IUS.object_id = O.object_id
GO

查找索引碎片:

SELECT O.name AS ObjectName ,
        I.name AS IndexName ,
        IPS.avg_page_space_used_in_percent AS AverageSpaceUsedInPages ,
        IPS.avg_fragmentation_in_percent AS AverageFragmentation ,
        IPS.fragment_count AS FragmentCount ,
        suggestedIndexOperation = CASE WHEN IPS.avg_fragmentation_in_percent <= 30
                                       THEN 'ReOrganize Index'
                                       ELSE 'ReBuild Index'
                                  END
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED')
        AS IPS
        INNER JOIN sys.indexes AS I ON IPS.index_id = I.index_id
                                       AND IPS.object_id = I.object_id
        INNER JOIN sys.objects AS O ON IPS.object_id = O.object_id
WHERE IPS.avg_fragmentation_in_percent > 5
ORDER BY AverageFragmentation DESC 

GO

分析:

         SQLServer提供缺失索引的詳細情況。缺失索引是指在數據庫中不存在的索引,但是如果創建,查詢將會得益並運行得更快。可以關聯兩個DMVsys.dm_db_missing_index_groupssys.dm_db_missing_index_group_stats。其中DMVsys.dm_db_missing_index_groups_stats返回關於如果創建了缺失索引,將會對查詢有多少可能性的提高的詳細信息。注意從這個視圖中查找的avg_user_impact列,這裏間接地通過這列來和Sys.dm_db_missing_index_detailssys.dm_db_missing_index_groups關聯。

DTA(數據庫優化引擎顧問)類似,DMV可能會建議廣泛使用很多INCLUDE列在索引中。所以你不應該不顧一切把所有索引全部創建。因爲這對你的DML操作可能會帶來比較大的影響,如增刪改等操作。

在第二個查詢DMO中,返回了特定索引的查找和掃描數量。爲了返回索引名稱和對象名稱,關聯了sys.indexessys.objects這兩個目錄視圖。

       最後就是查找碎片,這裏使用了DMF而不是DMVsys.dm_db_index_physical_stats()函數。留意一下,這裏使用了DB_ID()函數,因爲希望得到當前數據庫的所有索引信息,所以用這個函數即可。爲了得到索引名和對象名,關聯了sys.indexexsys.objects目錄視圖。


三、用DMV和DMF監控TempDB 

前言:

        我們都知道TempDBSQLServer的系統數據庫,且SQLServer的日常運作嚴重依賴這個庫。因此,監控TempDB的性能問題尤爲重要。在過去很長一段時間裏面,很多人都忽略了TempDB的重要性並忽略了它的性能問題。這並不是一件好事,因爲TempDB的性能會影響其他用戶數據庫的性能,所以需要時時刻刻注意TempDB的性能。

        在一些查詢的聚合、排序操作,遊標操作和版本存儲操作,聯機索引創建,用戶對象存儲如臨時表等,都將用到TempDB,作爲DBA,需要經常監控TempDB,以便識別出資源消耗較大的操作。此時可以使用數據庫相關的DMVs來完成。

        在使用這些DMVs時,要清楚一些基礎概念,SQLServer是如何組織數據的。所以先來了解頁和區。

就像你所知道的,SQLServer主要通過兩類文件來存儲數據庫。就是數據文件(mdf/ndf)和日誌文件(ldf)。這裏只討論數據文件。因爲頁和區不適用於日誌文件。

        數據文件是SQLServer存儲數據庫的對象如表和索引的一種格式化文件。這些數據文件由更小的單元組成,這些單元叫做頁。一個頁存放8K的數據。

        另外,區也有頁來存放,一個區有8個順序頁組成。所以,一個區有64K1MB16個區。

包含數據的對象會分配到區中的頁上。有兩類的區——統一區和混合區,一個統一區被一個單獨對象所獨有,混合區可以存放能夠放進8個頁的8個不同對象。因爲混合區可以共享整個區,所以也叫做共享區。當表很小時,會放入混合區,直到足夠大佔據一個區時,混合區就會整合成一個統一區。

        本文將演示如何監控TempDB的性能。同時可以識別出引起TempDB空間增加的會話和任務。

      

準備工作:

本文將產生1000萬數據,並存放到TempDB的局部臨時表中。然後監控頁分配和重新分配的情況。

 

步驟:

1、  連到SQLServer

2、  輸入以下代碼:

USE tempdb

GO

--檢查表是否存在

IF OBJECT_ID('[dbo].[tbl_TempDBStats]') IS NOT NULL 

    DROP TABLE [dbo].[tbl_TempDBStats]

--創建表用於存放頁分配的明細

CREATE TABLE [dbo].[tbl_TempDBStats]

    (

      session_id SMALLINT ,

      database_id SMALLINT ,

      user_objects_alloc_page_count BIGINT ,

      user_objects_dealloc_page_count BIGINT ,

      internal_objects_alloc_page_count BIGINT ,

      internal_objects_dealloc_page_count BIGINT

    )

GO

--收集當前會話在執行查詢之前的分配明細

INSERT INTO [dbo].[tbl_TempDBStats]

        SELECT session_id ,

                database_id ,

                user_objects_alloc_page_count ,

                user_objects_dealloc_page_count ,

                internal_objects_alloc_page_count ,

                internal_objects_dealloc_page_count

        FROM sys.dm_db_session_space_usage

        WHERE session_id = @@SPID

GO

--檢查表是否存在

IF OBJECT_ID('TempDB.dbo.#tbl_SampleData') IS NOT NULL 

    DROP TABLE TempDB.dbo.#tbl_SampleData

GO

--產生萬數據並插入臨時表

SELECT TOP 10000000

        SC1.object_id ,

        SC1.column_id ,

        SC1.name ,

        SC1.system_type_id

INTO TempDB.dbo.#tbl_SampleData

FROM sys.columns AS SC1

        CROSS JOIN sys.columns AS SC2

        CROSS JOIN sys.columns AS SC3

ORDER BY SC1.column_id

GO


--重新收集插入數據後的數據頁分配情況

INSERT INTO [dbo].[tbl_TempDBStats]

        SELECT session_id ,

                database_id ,

                user_objects_alloc_page_count ,

                user_objects_dealloc_page_count ,

                internal_objects_alloc_page_count ,

                internal_objects_dealloc_page_count

        FROM sys.dm_db_session_space_usage

        WHERE session_id = @@SPID


3、  然後輸入以下代碼,並注意執行前後的數據差異:

USE tempdb

GO

SELECT *

FROM [dbo].[tbl_TempDBStats]


4、  結果如下:

5、  運行以下查詢查找TempDB空間分配情況:

SELECT DB_NAME(FSU.database_id) AS DatabaseName ,

        MF.name AS LogicalFileName ,

        MF.physical_name AS PhysicalFilePath ,

        SUM(FSU.unallocated_extent_page_count) * 8.0 / 1024 AS Free_Space_In_MB ,

        SUM(FSU.version_store_reserved_page_count

            + FSU.user_object_reserved_page_count

            + FSU.internal_object_reserved_page_count

            + FSU.mixed_extent_page_count) * 8.0 / 1024 AS Used_Space_In_MB

FROM sys.dm_db_file_space_usage AS FSU

        INNER JOIN sys.master_files AS MF ON FSU.database_id = MF.database_id

                                             AND FSU.file_id = MF.file_id

GROUP BY FSU.database_id ,

        FSU.file_id ,

        MF.name ,

        MF.physical_name


6、  結果如下:

分析:

        在本文的開片中,首先創建了一個表tbl_TempDBStats以便存放頁分配和釋放的統計數據。然後通過查詢sys.dm_db_session_space_usage,獲取分析信息。把所有用戶定義對象和系統內置對象都插入表中。

        下一個查詢將產生1000萬數據,並插入臨時表#tbl_SampleData。使tempdb的分配情況發生改變。

        插入數據以後,檢查tbl_TempDBStats表,可以得出一些對比信息,最後通過一個DMVsys.dm_db_file_space_usage。可以看出以MB爲單位的分配情況。

        注意:sys.dm_db_file_space_usage ,sys.dm_db_session_space_usage這兩個DVM僅適用於tempdb

四、用DMV和DMF監控磁盤IO         

前言:

        本文爲本系列最後一篇,作爲DBA,你必須經常關注磁盤的I/O問題,一旦出現問題,要儘快分析出是什麼問題。SQLServer同樣提供了一些列與I/O相關的DMO來做監控。

        本文介紹如何使用DMO來監控I/O子系統的性能並找到I/O瓶頸。通過本文,可以區分不同數據庫的I/O使用模式。一旦發現有數據庫的I/O很高,可能需要考慮把數據庫遷移到單獨的磁盤,或者深入研究I/O產生的問題。

1. 監控SQLServer實例上的日誌文件和數據文件:

SELECT DB_NAME(VFS.database_id) AS DatabaseName ,

        MF.name AS LogicalFileName ,

        MF.physical_name AS PhysicalFileName ,

        CASE MF.type

          WHEN 0 THEN 'Data File'

          WHEN 1 THEN 'Log File'

        END AS FileType ,

        VFS.num_of_reads AS TotalReadOperations ,

        VFS.num_of_bytes_read AS TotalBytesRead ,

        VFS.num_of_writes AS TotalWriteOperations ,

        VFS.num_of_bytes_written AS TotalWriteOperations ,

        VFS.io_stall_read_ms AS TotalWaitTimeForRead ,

        VFS.io_stall_write_ms AS TotalWaitTimeForWrite ,

        VFS.io_stall AS TotalWaitTimeForIO ,

        VFS.size_on_disk_bytes AS FileSizeInBytes

FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS VFS

        INNER JOIN sys.master_files AS MF ON VFS.database_id = MF.database_id

                                             AND VFS.file_id = MF.file_id

ORDER BY VFS.database_id DESC


2. 清空數據緩存:

DBCC DROPCLEANBUFFERS

GO


3. 再次執行監控SQLServer實例上的日誌文件和數據文件:


4. 查看是否有IO掛起操作:

SELECT DB_NAME(VFS.database_id) AS DatabaseName ,

        MF.name AS LogicalFileName ,

        MF.physical_name AS PhysicalFileName ,

        CASE MF.type

          WHEN 0 THEN 'Data File'

          WHEN 1 THEN 'Log File'

        END AS FileType ,

        PIOR.io_type AS InputOutputOperationType ,

        PIOR.io_pending AS Is_Request_Pending ,

        PIOR.io_handle ,

        PIOR.scheduler_address

FROM sys.dm_io_pending_io_requests AS PIOR

        INNER JOIN sys.dm_io_virtual_file_stats(DB_ID('AdventureWorks'), NULL)

        AS VFS ON PIOR.io_handle = VFS.file_handle

        INNER JOIN sys.master_files AS MF ON VFS.database_id = MF.database_id

                                             AND VFS.file_id = MF.file_id

GO


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章