日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

收集的SQL Server性能相关资料

發布時間:2023/12/20 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 收集的SQL Server性能相关资料 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這是本人在工作中整理的關于SQL Server性能相關資料,便于隨時查閱

目錄

性能監視器指標

內存問題診斷

偵測 CPU 壓力

磁盤相關

內存

Memory Clerks

Buffer Pool

Plan Cache

CPU

線程

硬件信息

等待信息

SOS_SCHEDULER_YIELD等待

CXPACKET等待

資源消耗統計

I/O

讀寫信息

常見問題

索引

MDV

統計?

日志

WRITELOG等待

LOGBUFFER等待

小結

相關SQL


?

?

性能監視器指標

內存問題診斷

Memory Manager\Total Server Memory(KB)

Buffer Pool的大小

?

Memory Manager\Target Server Memory(KB)

表示空閑的Buffer Pool大小。 Total和Target的值應該盡可能相同, 如果Total明顯小于Target, 可能意味著出現了內存壓力,需要更深入地研究。

?

Memory Manager\Granted Workspace Memory( KB)

當前查詢正在使用的總內存大小。

Workspace:指在查詢過程中,進行hash和排序操作時,臨時存儲數據的結果集所用的內存。如果在執行計劃中看到出現了hash或者sort操作符,那么就表示會使用這部分的內存完成處理。

Memory Grants:已經分配給查詢的那部分內存。 可以用過 sys. dm_exec_query_memory_grants查看。

另外, RESOURCE_ SEMAPHORE 等待狀態是針對 memory grants 的,所以如果在sys. dm_ os_ wait_ stats這個DMV中看到這個等待類型存在很久,并且處于前幾位,可能需要檢查內存是否足夠快。 如果內存授予(memory grants)太久,會導致查詢超時,可以使用SQL trace或者執行計劃查看是否存在hash或者sort warning這些信息。

?

Memory Manager\Maximum Workspace Memory( KB)

SQL Server 標記預留給某個查詢的總內存大小。

?

Memory Manager\Memory Grants Pending

正在隊列中的內存grants數量。

>2

Memory Manager\Memory Grants Outstanding

正在使用的內存grants數量。

?

Buffer Manager\Buffer Cache Hit Ratio

Percentage of pages that were found in the buffer pool without having to incur a read from disk.

>90%

Buffer Manager\Page Life Expectancy

代表著一個數據存在于Buffer Pool的時間。這個值越長越好,最低時間應該設置為300s。

>1000,至少為300

Buffer Manager\Page Lookups/sec

這個計數器用于衡量實例中的請求在buffer pool里面查詢的單獨頁數量。當這個數值很高時,可能意味著不高效的執行計劃,通常需要研究該執行計劃。一般數值很高是因為執行計劃中產生了大量的Page Lookups和Row Lookups。

Page Lookups:

Batch Request<100

Plan Cache\Cache hit Ratio

Ratio between cache hits and lookups

?

Memory:Available Mbytes

以字節表示的物理內存數量。此內存能立刻分配給一個進程或系統使用。它等于分配給待機(緩存的)、空閑和零分頁列表內存的總和。要獲得內存管理器的詳細解釋,請參閱 MSDN 和/或 Windows Server 2003 Resource Kit 里的系統性能和疑難解答指南章節。

?

Memory:Page Faults/sec

每秒鐘出錯頁面的平均數量。由于每個錯誤操作中只有一個頁面出錯,計算單位為每秒出錯頁面數量,因此這也等于頁面錯誤操作的數量。這個計數器包括硬錯誤(那些需要磁盤訪問的)和軟錯誤(在物理內存的其他地方找到的錯誤頁)。許多處理器可以在有大量軟錯誤的情況下繼續操作。但是,硬錯誤可以導致明顯的拖延。

?

Memory:Pages/sec

指為解決硬頁錯誤從磁盤讀取或寫入磁盤的速度。這個計數器是可以顯示導致系統范圍延緩類型錯誤的主要指示器。它是 Memory\\Pages Input/sec 和 Memory\\Pages Output/sec 的總和。是用頁數計算的,以便在不用做轉換的情況下就可以同其他頁計數如: Memory\\Page Faults/sec 做比較,這個值包括為滿足錯誤而在文件系統緩存(通常由應用程序請求)的非緩存映射內存文件中檢索的頁。

?

偵測 CPU 壓力

Access Methods\Forwarded Records/sec。

該計數器統計每秒通過正向記錄指針提取的記錄數,這個計數器用于衡量服務器中對Forwarded數據的訪問情況,通常來說,這個值不應該超過Batch Requests/sec的10%。雖然10%不是絕對值,但它是一個警告值。

?

Access Methods\FreeSpace Scans/sec。

這是關于堆表的另外一個計數器。當在堆表中插入數據時,它會標識發生了什么操作。

?

Access Methods\Full Scans/sec。

通過這個計數器可查看Full Scans/sec的值,這個值包含聚集、非聚集索引及堆表。高值意味著查詢存在性能問題,這種情況可能會引起Page Life Expectancy(用于衡量內存壓力的一個主要計數器)的變動,這將加大數據在內存中的存儲時間,并引起I/O問題。

Batch Requests:Full Scans<1000

Access Methods\Index Searches/sec

大部分情況下,索引查找會比索引掃描有效,這個計數器顯示出SQL Server實例上發生索引查找的比率,這個值相對于Full Scans/sec來說越高越好。

Index Searches:

Full Scans>1000

Access Methods\Page Splits/sec

對應于堆上的Forwarded Records,聚集索引上的就是Page Splits了。補充一下,雖然非聚集索引也有這個特性,但是由于沒有聚集索引的表就是堆表,所以堆表上的非聚集索引還是使用的Forwarded Records。Page Splits是一個較消耗資源的操作,而且在拆頁的時候會對原來的頁加上排他鎖,并且會產生碎片,所以應盡可能少用。

Batch Requests:Page Split>20

Locks(*)\Lock Wait Time(ms)

相對于前面的計數器,這類計數器更偏重于檢查索引的壓力情況。它可以衡量SQL Server花在索引、表、頁上鎖資源的時間。它沒有可參考值,但是可以作為一個歷史數據,然后用最近監控的數據和這個歷史數據對比,比值應該越低越好。

?

Locks(*)\Number of Deadlocks/sec。

極端情況下,不良的索引設計和過度鎖阻塞會引起死鎖(Deadlocks),這種情況是絕對不能容忍的。

=0

Processor/%Privileged Time

花費在執行Windows內核命令上的處理器時間的百分比。

?

Processor/%User Time

花費在處理應用程序如SQL Server上的處理器時間百分比。

?

Process(sqlservr. exe)/%Processor Time

每個處理器上所有進程的總處理時間。

?

SQL Statistics\Auto-Param Attempts/sec

Number of auto-parameterization attempts.

?

SQL Statistics\Failed Auto-params/sec

Number of failed auto-parameterizations.

?

SQL Statistics\Batch Requests/sec

Number of failed auto-parameterizations.

?

SQL Statistics\SQL Compilations/sec

Number of SQL compilations.

?

SQL Statistics\SQL Re-Compilations/sec

Number of SQL re-compiles.

?

磁盤相關

Physical Disk\Average Disk sec/Read

Avg. Disk sec/Read 指以秒計算的在此盤上讀取數據的所需平均時間。

?

Physical Disk\Average Disk sec/Write

Avg. Disk sec/Write 指以秒計算的在此盤上寫入數據的所需平均時間。

?

Physical Disk\Average Disk Read/Read Queue Length

Avg. Disk Read Queue Length 指讀取請求(為所選磁盤在實例間隔中列隊的)的平均數。

?

Physical Disk\Average Disk Read/Write Queue Length

Avg. Disk Write Queue Length 指寫入請求(為所選磁盤在實例間隔中列隊的)的平均數。

?

Physical Disk\Disk Reads/sec

Disk Reads/sec 指在此盤上讀取操作的速率。

<10ms=沒有性能問題 ·10~20ms=存在問題 ·20~50ms=性能很低 ·>50ms=性能問題嚴重

Physical Disk\Disk Writes/sec

Disk Writes/sec 指在此盤上寫入操作的速率。

<10ms=沒有性能問題 ·10~20ms=存在問題 ·20~50ms=性能很低 ·>50ms=性能問題嚴重

?

內存

Memory Clerks

-- 用于內存緩存的一種機制,

SELECT [type],

?????? memory_node_id,

?????? virtual_memory_reserved_kb,

?????? virtual_memory_committed_kb,

?????? awe_allocated_kb

FROM?? sys.dm_os_memory_clerks

ORDER? BY virtual_memory_reserved_kb DESC

?

Buffer Pool

SQL Server 內存中的最大消耗者。

--每個數據庫緩存大小

SELECT LEFT(CASE database_id

????????????? WHEN 32767 THEN 'ResourceDb'

????????????? ELSE Db_name(database_id)

??????????? END, 20)???????????????????????????????? AS Database_Name,

?????? Count(*)????????????????????????????????????? AS Buffered_Page_Count,

?????? Cast(Count(*) * 8 / 1024.0 AS NUMERIC(10, 2)) AS Buffer_Pool_MB

FROM?? sys.dm_os_buffer_descriptors

GROUP? BY Db_name(database_id),

????????? database_id

ORDER? BY Buffered_Page_Count DESC

?

--當前臟頁數

SELECT Db_name(database_id) AS 'Database',

?????? Count(page_id)?????? AS 'Dirty Pages( KB)'

FROM?? sys. dm_os_buffer_descriptors

WHERE? is_modified = 1

GROUP? BY Db_name(database_id)

ORDER? BY Count(page_id) DESC

?

Plan Cache

--執行計劃緩存

SELECT Count(*)???????????????????????????????????????? AS 'Number of Plans',

?????? Sum(Cast(size_in_bytes AS BIGINT)) / 1024 / 1024 AS 'Plan Cache Size (MB)'

FROM?? sys. dm_exec_cached_plans

?

--查看緩存對象的對應內存數。

SELECT objtype????????????????????????????????????? AS 'Cached Object Type',

?????? Count(*)???????????????????????????????????? AS 'Number of Plans',

?????? Sum(Cast(size_in_bytes AS BIGINT)) / 1048576 AS 'Plan Cache Size (MB)',

?????? Avg(usecounts)?????????????????????????????? AS 'Avg Use Count'

FROM?? sys. dm_exec_cached_plans

GROUP? BY objtype

?

CPU

線程

--當前系統最大線程數

SELECT max_workers_count

FROM?? sys.dm_os_sys_info

?

--當前工作線程

SELECT Count(*)

FROM?? sys.dm_os_workers

?

硬件信息

--NUMA配置

SELECT scheduler_id,

?????? cpu_id,

?????? parent_node_id,

?????? status

FROM?? sys.dm_os_schedulers

?

--得知超線程和核心方面的關系。

SELECT cpu_count???????????????????? AS [Logical(邏輯) CPU Count],

?????? hyperthread_ratio???????????? AS [Hyperthread(超線程) Ratio],

?????? cpu_count / hyperthread_ratio AS [Physical(物理) CPU Count],

?????? physical_memory_kb / 1024???? AS [Physical Memory (MB)]

FROM?? sys. dm_os_sys_info

?

等待信息

--等待類型中等待時間最長的10個類型。

SELECT TOP (10) wait_type,

??????????????? waiting_tasks_count,

??????????????? ( wait_time_ms - signal_wait_time_ms ) AS resource_wait_time,

??????????????? max_wait_time_ms,

??????????????? CASE waiting_tasks_count

????????????????? WHEN 0 THEN 0

????????????????? ELSE wait_time_ms / waiting_tasks_count

??????????????? END??????????????????????????????????? AS avg_wait_time

FROM?? sys.dm_os_wait_stats

WHERE? wait_type NOT LIKE '%SLEEP%'

?????? --去除不相關的等待類型

?????? AND wait_type NOT LIKE 'XE%'

?????? AND wait_type NOT IN

?????????? -- 去除系統類型

?????????? ( 'KSOURCE_WAKEUP', 'BROKER_TASK_STOP', 'FT_IFTS_SCHEDULER_IDLE_WAIT', 'SQLTRACE_BUFFER_FLUSH',

???????????? 'CLR_AUTO_EVENT', 'BROKER_EVENTHANDLER', 'BAD_PAGE_PROCESS', 'BROKER_TRANSMITTER',

???????????? 'CHECKPOINT_QUEUE', 'DBMIRROR_EVENTS_QUEUE', 'SQLTRACE_BUFFER_FLUSH', 'CLR_MANUAL_EVENT',

???????????? 'ONDEMAND_TASK_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH', 'LOGMGR_QUEUE', 'BROKER_RECEIVE_WAITFOR',

???????????? 'PREEMPTIVE_OS_GETPROCADDRESS', 'PREEMPTIVE_OS_AUTHENTICATIONOPS', 'BROKER_TO_FLUSH' )

ORDER? BY wait_time_ms DESC

?

?

SELECT wait_type,

?????? signal_wait_time_ms,

?????? wait_time_ms

FROM?? sys.dm_os_wait_stats

WHERE? wait_time_ms > 0

?????? AND wait_type NOT IN ( 'CLR_SEMAPHORE', 'CLR_AUTO_EVENT', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE',

????????????????????????????? 'SLEEP_TASK', 'SLEEP_SYSTEMTASK', 'SQLTRACE_BUFFER_FLUSH', 'WAITFOR',

????????????????????????????? 'LOGMGR_QUEUE', 'CHECKPOINT_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT',

????????????????????????????? 'BROKER_TO_FLUSH', 'BROKER_TASK_STOP', 'CLR_MANUAL_EVENT', 'DISPATCHER_QUEUE_SEMAPHORE',

????????????????????????????? 'FT_IFTS_SCHEDULER_IDLE_WAIT', 'XE_DISPATCHER_WAIT', 'XE_DISPATCHER_JOIN', 'SQLTRACE_INCREMENTAL_FLUSH_SLEEP' )

ORDER? BY signal_wait_time_ms DESC

?

SOS_SCHEDULER_YIELD等待

發生在一個任務自愿放棄當前的資源占用,讓給其他任務使用的時候,就像前面說的離開飲水機讓別人去接水。 現代關系型數據庫管理系統早已支持多個任務同時運行,SQL Server的運行機制之一就是減少runnable的線程等待,也就是說,SQL Server希望盡快運行runnable的線程。它以協同模式運行,在必要的時候,SQL Server會讓出某個資源來給其他線程,通常來說這種情況是臨時的。但是當長期、大量出現這種等待類型的時候,有可能意味著CPU存在壓力,這時候可以檢查這個DMV中的數據:sys.dm_os_schedulers,看看當前有多少runnable的任務在系統中運行。

--當前有多少runnable的任務在系統中運行

SELECT scheduler_id,

?????? current_tasks_count,

?????? runnable_tasks_count,

?????? work_queue_count,

?????? pending_disk_io_count

FROM?? sys.dm_os_schedulers

WHERE? scheduler_id < 255

通常我們需要關注runnable_tasks_count這個列的數據,如果見到長時間存在兩位數的數值(記住是長時間存在),就意味著CPU可能存在壓力,無法應付當前負載。

?

CXPACKET等待

CXPACKET 這種類型有點像平時所說的木桶效應,一個木桶的容量取決于組成木桶最短的那塊木條的長度。如果一個查詢由多個線程組成,那么只有在最慢的那個線程完成之后,整個查詢才會完成。在這種情況下,SQL Server就出現了CXPACKET等待。 CXPACKET是其中一個最常見的并行等待,在多CPU的環境下,這種等待經常會出現。并行執行最重要的目的就是使得運算更快,一個單獨的查詢可以使用多個線程來共同完成,每個線程會單獨處理數據集的一部分。但應該注意的是,某些等待并不總是表示系統性能存在問題,CXPACKET就是其中一種。比如有一家軟件公司,通常會招聘多個開發人員去完成開發工作。但是每天上下班時,總需要一個人一個人串行“打卡”,這時候CXPACKET就會出現在打卡的過程中,因為這個時候必須串行而不是并行。你可能覺得打卡過程中所用的時間是浪費的,但是從整體來說,你雇用更多的人去完成功能開發,理想情況下是可以加快項目的開發進度的,不應該因為打卡這幾秒鐘的浪費而無視他們在一天中對進度的貢獻。 在并行過程中,如果某個線程處于落后狀態,CXPACKET等待狀態就會產生。在上面的例子中,如果你為了移除這種等待狀態而減少雇員,比如只留下一個,那么你整體的項目進度將會嚴重延遲。 但是畢竟出現等待狀態就是表示有一定的資源問題,所以需要針對這種情況進行分析。前面提到過,對問題的分析要全面、整體,并且要區分應用系統類型。

OLTP系統

它的特點是事務數量多,但是正常來說,事務的持續時間不會很久。

如果CXPACKET等待狀態頻繁出現,且持續時間很長,那就意味著性能可能有問題了。

理想情況下事務很短,這時候就沒有必要通過并行運行來提高運行速度了。所以對于這類系統,有一個極端方法(如非必要不要用),即把最大并行度(Max Degree of Parallelism)設為1,強制SQL Server不去使用并行操作,從而減少不必要的資源等待。

OLAP等系統

它的事務量可能不多,但是持續時間往往會很久。

由于事務普遍較長,所以并行操作往往能提高速度和資源利用率。這時候可以讓SQL Server自己控制并行,也就是把最大并行度設為0(即不限制)。

--計劃緩存中存在并行查詢的語句

SELECT TOP 10 p.*,

????????????? q.*,

????????????? qs.*,

????????????? cp.plan_handle

FROM?? sys.dm_exec_cached_plans cp

?????? CROSS apply sys.Dm_exec_query_plan(cp.plan_handle) p

?????? CROSS apply sys.Dm_exec_sql_text(cp.plan_handle) AS q

?????? JOIN sys.dm_exec_query_stats qs

???????? ON qs.plan_handle = cp.plan_handle

WHERE? cp.cacheobjtype = 'Compiled Plan'

?????? AND p.query_plan.value('declare namespace p="http://schemas.microsoft.com/sqlserver/2004/07/showplan";?

??????? max(//p:RelOp/@Parallel)', 'float') > 0

ORDER? BY total_worker_time DESC

OPTION (MAXDOP 1)

?

資源消耗統計

--CPU最高消耗的10個語句

SELECT TOP 10 Substring(ST.text, ( QS.statement_start_offset / 2 ) + 1, ( ( CASE statement_end_offset

????????????????????????????????????????????????????????????????????????????? WHEN -1 THEN Datalength(st.text)

????????????????????????????????????????????????????????????????????????????? ELSE QS.statement_end_offset

??????????????????????????????????????????????????????????????????????????? END - QS.statement_start_offset ) / 2 ) + 1) AS statement_text,

????????????? execution_count,

????????????? total_worker_time / 1000?????????????????????????????????????????????????????????????????????????????????? AS total_worker_time_ms,

????????????? ( total_worker_time / 1000 ) / execution_count???????????????????????????????????????????????????????????? AS avg_worker_time_ms,

????????????? total_logical_reads,

????????????? total_logical_reads / execution_count????????????????????????????????????????????????????????????????????? AS avg_logical_reads,

????????????? last_logical_reads,

????????????? total_logical_writes,

????????????? total_logical_writes / execution_count???????????????????????????????????????????????????????????????????? AS avg_logical_writes,

????????????? last_logical_writes,

????????????? total_elapsed_time / 1000????????????????????????????????????????????????????????????????????????????????? AS total_elapsed_time_ms,

????????????? ( total_elapsed_time / 1000 ) / execution_count??????????????????????????????????????????????????????????? AS avg_elapsed_time_ms,

????????????? last_elapsed_time / 1000,

????????????? qp.query_plan

FROM?? sys.dm_exec_query_stats qs

?????? CROSS APPLY sys.Dm_exec_sql_text(qs.sql_handle) st

?????? CROSS APPLY sys.Dm_exec_query_plan(qs.plan_handle) qp

ORDER? BY total_worker_time DESC

?

--找出使用頻率最高的20%的查詢

SELECT TOP 20 PERCENT cp.usecounts???? AS ' 使用次數',

????????????????????? cp.cacheobjtype? AS ' 緩存類型',

????????????????????? cp.objtype?????? AS [ 對象類型],

????????????????????? st.text????????? AS 'TSQL',

????????????????????? --cp.plan_handle AS ' 執行計劃',

????????????????????? qp.query_plan??? AS ' 執行計劃',

????????????????????? cp.size_in_bytes AS ' 執行計劃占用空間( Byte)'

FROM?? sys.dm_exec_cached_plans cp

?????? CROSS APPLY sys.Dm_exec_sql_text(plan_handle) st

?????? CROSS APPLY sys.Dm_exec_query_plan(plan_handle) qp

ORDER? BY usecounts DESC

?

I/O

讀寫信息

--查看當前數據庫文件中的IO情況

SELECT Db_name(Db_id())?????????????????????????????????????????????????????????????????????????????????? AS [Database Name],

?????? [file_id],

?????? num_of_reads,

?????? num_of_writes,

?????? num_of_bytes_read,

?????? num_of_bytes_written,

?????? Cast(100. * num_of_reads / ( num_of_reads + num_of_writes ) AS DECIMAL(10, 1))???????????????????? AS [# Reads Pct],

?????? Cast(100. * num_of_writes / ( num_of_reads + num_of_writes ) AS DECIMAL(10, 1))??????????????????? AS [# Write Pct],

?????? Cast(100. * num_of_bytes_read / ( num_of_bytes_read + num_of_bytes_written ) AS DECIMAL(10, 1))??? AS [Read Bytes Pct],

?????? Cast(100. * num_of_bytes_written / ( num_of_bytes_read + num_of_bytes_written ) AS DECIMAL(10, 1)) AS [Written Bytes Pct]

FROM?? sys. Dm_io_virtual_file_stats(Db_id(), NULL);

?

--計劃緩存中存儲過程的邏輯寫排名,主要是寫操作的壓力

SELECT p. NAME????????????????? AS [SP Name],

?????? qs. total_logical_writes AS [TotalLogicalWrites],

?????? qs. execution_count,

?????? qs. cached_time

FROM?? sys. procedures AS p

?????? INNER JOIN sys. dm_exec_procedure_stats AS qs

?????????????? ON p.[object_id] = qs. [object_id]

WHERE? qs. database_id = Db_id()

?????? AND qs. total_logical_writes > 0

ORDER? BY qs. total_logical_writes DESC;

?

常見問題

解決PAGEIOLATCH等待

潛在問題

數據從磁盤加載到內存buffer中的時間不會很長,一旦數據進入buffer,提取數據會很快,并且查找過程不會產生任何等待。但是也有特殊情況,如果有10個任務都需要同時請求相同的數據,第一個任務會申請加載數據,其他9個任務都必須等待,直到第一個任務的數據加載完畢為止。如果這時磁盤已經超負荷,那么第一個請求會花費較長的時間。同樣,如果內存不足,緩存在buffer中的數據會過早地被沖刷掉(從buffer中清空),從而引起9個任務再次等待下一輪的加載。

降低PAGEIOLATCH等待

當buffer正在加載和卸載時,都會對其中的數據加上閂鎖。這意味著其他進程必須等待,直到釋放閂鎖且數據依舊存在于buffer中為止。快速地加載和長時間駐留能最大限度地降低等待,這類等待和其他等待類似,當遇到相關問題時,可以評估下面的方案是否可行。

提升I/O子系統的速度。

當存在內存問題或者壓力出現時也會引起這種等待,檢查內存相關的計數器,查看是否存在內存問題,如果存在,嘗試優化或者改善內存。

將LDF/MDF/tempdb的文件分開存放,減少資源爭用。

檢查文件統計信息,看看高I/O讀寫操作出現在什么文件上。

檢查系統是否有合適的索引,丟失索引和不合理的索引都會造成大面積的掃描,通過添加有效的索引可減少I/O請求,緩解I/O壓力。使用覆蓋索引來替代聚集索引是一個不錯的選擇,可以明顯降低CPU、內存和I/O的壓力(因為一般非聚集索引包含的列都比聚集索引少,聚集索引實際上是全表索引)。

更新統計信息,使SQL Server查詢優化器能選擇最優執行計劃。

檢查下面的性能計數器。

SQL Server:Memory Manager\Memory Grants Pending>2

SQL Server:Memory Manager\Memory Grants Outstanding

SQL Server:Buffer Manager\Buffer Hit Cache Ratio>90%

SQL Server:Buffer Manager\Page Life Expectancy>1000,至少為300

Memory:Available Mbytes Memory:Page Faults/sec ·檢查磁盤相關的計數器。

Average Disk sec/Read Average Disk sec/Write Average Disk Read/Write Queue Lenght

?

索引

MDV

sys.index_columns

提供了索引內包含的列,也就是索引鍵。每個鍵一行,通過關聯其他DMV 就可以獲得索引定義的列情況。

sys.xml_indexes

和sys.indexes 類似,但是主要針對XML 索引。

sys.spatial_indexes

也和sys.indexes 類似,主要針對spatial 索引。

sys.column_store_dictionaries

sys.column_store_segments

主要用于描述從SQL Server 2012 開始引入的列存儲索引信息。

sys.dm_db_index_physical_stats

索引碎片

sys.dm_db_missing_index_details

缺失索引相關

sys.dm_db_missing_index_columns

缺失索引相關

sys.dm_db_missing_index_group_stats

缺失索引相關

sys.dm_db_missing_index_groups

缺失索引相關

?

統計?

SELECT '[' + Db_name() + '].[' + su.[name] + '].[' + o.[name]

?????? + ']'????????????????? AS [statement],

?????? i.[name]?????????????? AS [index_name],

?????? ddius.[user_seeks] + ddius.[user_scans]

?????? + ddius.[user_lookups] AS [user_reads],

?????? ddius.[user_updates]?? AS [user_writes],

?????? Sum(SP.rows)?????????? AS [total_rows]

FROM?? sys.dm_db_index_usage_stats ddius

?????? INNER JOIN sys.indexes i

?????????????? ON ddius.[object_id] = i.[object_id]

????????????????? AND i.[index_id] = ddius.[index_id]

?????? INNER JOIN sys.partitions SP

?????????????? ON ddius.[object_id] = SP.[object_id]

????????????????? AND SP.[index_id] = ddius.[index_id]

?????? INNER JOIN sys.objects o

?????????????? ON ddius.[object_id] = o.[object_id]

?????? INNER JOIN sys.sysusers su

?????????????? ON o.[schema_id] = su.[UID]

WHERE? ddius.[database_id] = Db_id() -- current database only

?????? AND Objectproperty(ddius.[object_id], 'IsUserTable') = 1

?????? AND ddius.[index_id] > 0

GROUP? BY su.[name],

????????? o.[name],

????????? i.[name],

????????? ddius.[user_seeks] + ddius.[user_scans]

????????? + ddius.[user_lookups],

????????? ddius.[user_updates]

HAVING ddius.[user_seeks] + ddius.[user_scans]

?????? + ddius.[user_lookups] = 0

ORDER? BY ddius.[user_updates] DESC,

????????? su.[name],

????????? o.[name],

????????? i.[name]

?

--查找未被使用過的索引

SELECT Object_name(i.object_id)????????????????????????????????????? AS table_name,

?????? COALESCE(i.NAME, Space(0))??????????????????????????????????? AS index_name,

?????? ps.partition_number,

?????? ps.row_count,

?????? Cast(( ps.reserved_page_count * 8 ) / 1024.AS DECIMAL(12, 2)) AS size_in_mb,

?????? COALESCE(ius.user_seeks, 0)?????????????????????????????????? AS user_seeks,

?????? COALESCE(ius.user_scans, 0)?????????????????????????????????? AS user_scans,

?????? COALESCE(ius.user_lookups, 0)???????????????????????????????? AS user_lookups,

?????? i.type_desc

FROM?? sys.all_objects t

?????? INNER JOIN sys.indexes i

?????????????? ON t.object_id = i.object_id

?????? INNER JOIN sys.dm_db_partition_stats ps

?????????????? ON i.object_id = ps.object_id

????????????????? AND i.index_id = ps.index_id

?????? LEFT OUTER JOIN sys.dm_db_index_usage_stats ius

??????????????????? ON ius.database_id = Db_id()

?????????????????????? AND i.object_id = ius.object_id

?????????????????????? AND i.index_id = ius.index_id

WHERE? i.type_desc NOT IN ( 'HEAP', 'CLUSTERED' )

?????? AND i.is_unique = 0

?????? AND i.is_primary_key = 0

?????? AND i.is_unique_constraint = 0

?????? AND COALESCE(ius.user_seeks, 0) <= 0

?????? AND COALESCE(ius.user_scans, 0) <= 0

?????? AND COALESCE(ius.user_lookups, 0) <= 0

ORDER? BY Object_name(i.object_id),

????????? i.NAME

?

--寫操作還是遠大于讀操作的索引

SELECT Object_name(ddius.[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 ddius WITH ( NOLOCK )

?????? INNER JOIN sys.indexes AS i WITH ( NOLOCK )

?????????????? ON ddius.[object_id] = i.[object_id]

????????????????? AND i.index_id = ddius.index_id

WHERE? Objectproperty(ddius.[object_id], 'IsUserTable') = 1

?????? AND ddius.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;

?

--索引上的碎片

SELECT '[' + Db_name() + '].['

?????? + Object_schema_name( ddips.[object_id], Db_id())

?????? + '].['

?????? + Object_name(ddips.[object_id], Db_id())

?????? + ']'????????????????????????????????????????????????? AS [statement],

?????? i.[name]?????????????????????????????????????????????? AS [index_name],

?????? ddips.[index_type_desc],

?????? ddips.[partition_number],

?????? ddips.[alloc_unit_type_desc],

?????? ddips.[index_depth],

?????? ddips.[index_level],

?????? Cast(ddips.[avg_fragmentation_in_percent] AS SMALLINT) AS [avg_frag_%],

?????? Cast(ddips.[avg_fragment_size_in_pages] AS SMALLINT)?? AS [avg_frag_size_in_pages],

?????? ddips.[fragment_count],

?????? ddips.[page_count]

FROM?? sys.Dm_db_index_physical_stats(Db_id(), NULL, NULL, NULL, 'limited') ddips

?????? INNER JOIN sys.[indexes] i

?????????????? ON ddips.[object_id] = i.[object_id]

????????????????? AND ddips.[index_id] = i.[index_id]

WHERE? ddips.[avg_fragmentation_in_percent] > 15

?????? AND ddips.[page_count] > 500

ORDER? BY ddips.[avg_fragmentation_in_percent],

????????? Object_name(ddips.[object_id], Db_id()),

????????? i.[name]

?

日志

WRITELOG等待

這是日志等待中最常見的等待類型。在事務量很高的系統中,這種等待比較常見。當數據被修改時,在log cache和buffer cache中都會有記錄,如果在log cache中的數據在checkpoint時寫入磁盤,就會發生這種等待。但是有時候在客戶端,用戶會停止一個正在運行并且運行了很久的事務,這時會引起其回滾,這也就會導致這種等待的發生。

降低WRITELOG等待

把日志文件和數據文件及其他文件如TEMPDB存放到獨立的磁盤中。另外就是避免類似游標等的低效操作,同時加快提交事務的頻率,最后檢查I/O相關的計數器。 除此之外,刪除沒用的非聚集索引、減少日志開銷、修改索引鍵或使用填充因子減少頁分裂(第6章介紹過)、修改程序架構、把負載分攤到多個服務器或者數據庫中,這些手段都能減少出現這類等待的情況。

不要一見到這種等待就以為是I/O問題,也不要直接增加日志文件。上面已經說過,增加日志文件解決不了這類問題。 應該進行如下更加深入的分析:

查看sys.dm_io_virtual_file_stats的數據。

查看LOGBUFFER等待(下面介紹),看是否存在對日志緩沖區(log buffer)的爭搶。

查看日志文件所在磁盤的磁盤等待隊列。

查看事務的平均大小。

查看是否有大量的頁分裂,因為這樣也會導致大量的日志。

?

LOGBUFFER等待

這種等待類型相對較少出現,當一個任務正在等待存儲記錄到log buffer時,就會產生這種等待。這種等待類型的高值可能表示這日志所在的磁盤無法響應請求。

降低LOGBUFFER等待

不同的原因解決方案不同,通常包括合理存放各類文件、避免類似游標等編程技巧及加快事務提交的頻率等。

?

小結

可以查看sys.fn_vertualfilestats函數找到I/O相關的問題,并且可檢查I/O相關的計數器,比如使用SELECT * FROM fn_virtualfilestats(1,1)來查看數據庫ID為1、文件號為1的統計信息。

WRITELOG和LOGBUFFER等待的處理手段非常類似,它們的確有共同點,但是不要認為它們是相同的,需要分開對待。

?

相關SQL

--檢查活動事務的日志情況

SELECT DTST.[session_id],

?????? DES.[login_name]?????????????????????????????? AS [Login Name],

?????? Db_name(DTDT.database_id)????????????????????? AS [Database],

?????? DTDT.[database_transaction_begin_time]???????? AS [Begin Time],-- DATEDIFF(ms,DTDT.[database_transaction_begin_time], GETDATE()) AS [Durationms],

?????? CASE DTAT.transaction_type

???????? WHEN 1 THEN 'Read/write'

???????? WHEN 2 THEN 'Read-only'

???????? WHEN 3 THEN 'System'

???????? WHEN 4 THEN 'Distributed'

?????? END??????????????????????????????????????????? AS [Transaction Type],

?????? CASE DTAT.transaction_state

???????? WHEN 0 THEN 'Not fully initialized'

???????? WHEN 1 THEN 'Initialized, not started'

???????? WHEN 2 THEN 'Active'

???????? WHEN 3 THEN 'Ended'

???????? WHEN 4 THEN 'Commit initiated'

???????? WHEN 5 THEN 'Prepared, awaiting resolution'

???????? WHEN 6 THEN 'Committed'

???????? WHEN 7 THEN 'Rolling back'

???????? WHEN 8 THEN 'Rolled back'

?????? END??????????????????????????????????????????? AS [Transaction State],

?????? DTDT.[database_transaction_log_record_count]?? AS [Log Records],

?????? DTDT.[database_transaction_log_bytes_used]???? AS [Log Bytes Used],

?????? DTDT.[database_transaction_log_bytes_reserved] AS [Log Bytes RSVPd],

?????? DEST.[text]??????????????????????????????????? AS [Last Transaction Text],

?????? DEQP.[query_plan]????????????????????????????? AS [Last Query Plan]

FROM?? sys.dm_tran_database_transactions DTDT

?????? INNER JOIN sys.dm_tran_session_transactions DTST

?????????????? ON DTST.[transaction_id] = DTDT.[transaction_id]

?????? INNER JOIN sys.[dm_tran_active_transactions] DTAT

?????????????? ON DTST.[transaction_id] = DTAT.[transaction_id]

?????? INNER JOIN sys.[dm_exec_sessions] DES

?????????????? ON DES.[session_id] = DTST.[session_id]

?????? INNER JOIN sys.dm_exec_connections DEC

?????????????? ON DEC.[session_id] = DTST.[session_id]

?????? LEFT JOIN sys.dm_exec_requests DER

????????????? ON DER.[session_id] = DTST.[session_id]

?????? CROSS APPLY sys.Dm_exec_sql_text(DEC.[most_recent_sql_handle]) AS DEST

?????? OUTER APPLY sys.Dm_exec_query_plan(DER.[plan_handle]) AS DEQP

ORDER? BY DTDT.[database_transaction_log_bytes_used] DESC; -- ORDER BY [Duration ms] DESC;

?

?

?

總結

以上是生活随笔為你收集整理的收集的SQL Server性能相关资料的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。