最近重新翻看The Accidental DBA,将Troubleshooting Performance部分稍作整理,方便以后查阅。此篇是Part 2
Part 1:The Accidental DBA:SQL Server Backup
Part 3:The Accidental DBA:Troubleshooting
一、Baselines

网友提供的性能基线的含义:每天使用windows性能计数器定时(周期为一个月,具体需要根据自己的需求)收集服务器硬件信息,然后对硬件信息进行分析统计,计算平均值、最大值、最小值,用来与之后每天硬件信息进行比较,从而快速的估算服务器硬件状态。

之前对基线的理解一直停留在使用Perfmon收集几个计数器,然后拿收集到的数值和网上推荐的数值进行对比,得以判别是否异常。
数据库服务器的基线的作用:
1、帮助你发现在它成为问题之前发生了什么变化
2、允许你主动调整你的数据库
3、允许你使用历史信息解决问题
4、提供用于环境和数据趋势的数据
5、捕获数据,提供给管理层,以及服务器和存储管理员,用于资源和容量规划
基线详细内容可参考:Capturing Baseline Data
二、Tools for On-Going Monitoring
2.1、Performance Monitor and PAL
Performance Monitor(PerfMon)提供了大量关于Windows和SQL Server的配置选项,你可以根据需要对不同的服务器进行调整,或者每次都使用相同的模板。它允许你在指定的时间段内生成一个全面的性能概要,并且你可以实时查看性能。
性能计数器的捕获可参考PerfMon模板;性能监视器文件的分析可借助PAL工具
2.2、SQL Trace and Trace Analysis Tools
客户端(Profiler)获取跟踪可参考:Trace-跟踪高消耗的语句需添加哪些事件;服务器端跟踪可参考:模板-Trace;导出正在运行的跟踪模板可参考:Trace-导出已有的服务器端跟踪
分析跟踪文件的工具有ClearTraceRML Utilities for SQL Server
对于SQL Server 2012及以上版本,推荐使用Extended Events代替Trace~
2.3、SQLNexus
SQLNexus用于分析SQLDiagPSSDiag捕获的数据。我们可以自定义SQLDiag和PSSDiag的默认模版:SQLdiag-配置文件-PerfmonCollectorSQLdiag-配置文件-ProfilerCollectorSQLdiag-配置文件-扩展
收集SQLDiag数据过于繁琐,现在很少有人使用SQLNexus工具~
2.4、Essential DMVs for Monitoring
DMVs非常实用,每次需要使用的时候到处查找,得找个时间把这个坑填补一番

sys.dm_os_wait_stats --I want to know what SQL Server is waiting on, when there is a problem and when there isn’t.  
sys.dm_exec_requests --When I want to see what’s executing currently, this is where I start.
sys.dm_os_waiting_tasks --In addition to the overall waits, I want to know what tasks are waiting right now (and the wait_type).
sys.dm_exec_query_stats --execution count and resource usage
sys.dm_exec_query_plan --This DMV has cached plans as well as those for queries that are currently executing.
sys.dm_db_stats_properties --I always take a look at statistics in new systems, and when there’s a performance issue, initially just to check when they were last updated and the sample size.

Glenn had a great set of diagnostic queries to use for monitoring and troubleshooting.
三、Are your indexing strategies working?
对于一个全新的系统,可以按照以下三个步骤分析索引信息
step1、是否存在无效的索引
step2、是否存在臃肿和不健康的索引
step3、是否需要添加新索引
3.1、Getting rid of the dead weight
3.1.1、Fully duplicate indexes
如果不知道索引的内部机制,可能会比你想象的更难以识别重复索引。它并不总是简单的col1列上的Index1和col1上的Index2。
在内部,SQL Server会添加列到索引,大多数命令(比如sp_helpindex)不会显示这些内部添加的列。
可以参考Identifying Duplicate Indexes得到重复索引信息。
注意:你可能会打断使用索引提示的应用程序,因此,请当心!通常在删除索引之前最好先禁用一段时间。
3.1.2、Unused Indexes
从未使用的索引和重复索引一样消耗资源。你可以使用sys.dm_db_index_usage_stats获取索引的使用情况,注意在sqlserver2012某些版本,重建索引会清空sys.dm_db_index_usage_stats中此索引的条目
user_updates列只反映语句的数量,不反映影响的行数。例如,我执行以下语句

UPDATE Table SET ColumnX = VALUE

影响10000行,那么表和包含ColumnX列的索引对应的user_updates都会累加1(update/delete/insert 类似)

--数据表、索引参考Identifying Duplicate Indexes(http://www.cnblogs.com/Uest/p/6679504.html)中的测试数据
USE Test
GO
SELECT * 
INTO Test.dbo.SalesOrderDetail_IndexUsage
FROM AdventureWorks2008R2.Sales.SalesOrderDetail
GO
--CREATE UNIQUE CLUSTERED INDEX SalesOrderDetail_IndexUsage ON dbo.SalesOrderDetail(SalesOrderDetailID)
CREATE INDEX IX_SalesOrderID1 ON dbo.SalesOrderDetail_IndexUsage(SalesOrderID,rowguid,SalesOrderDetailID) INCLUDE(LineTotal)
--CREATE INDEX IX_SalesOrderID2 ON dbo.SalesOrderDetail_IndexUsage(SalesOrderID,rowguid) INCLUDE(LineTotal)
--CREATE INDEX IX_SalesOrderID3 ON dbo.SalesOrderDetail_IndexUsage(SalesOrderID,rowguid) INCLUDE(SalesOrderDetailID,LineTotal)
--CREATE UNIQUE INDEX IX_SalesOrderID4 ON dbo.SalesOrderDetail_IndexUsage(SalesOrderID,rowguid) INCLUDE(SalesOrderDetailID,LineTotal)
GO

--查看索引使用情况
select o.name,i.index_id,i.name,user_seeks,user_scans,user_lookups,user_updates
from sys.dm_db_index_usage_stats ddus
inner join sys.tables o
on ddus.object_id=o.object_id
inner join sys.indexes i
on ddus.index_id=i.index_id
and ddus.object_id=i.object_id
where database_id = db_id()
and o.name='SalesOrderDetail_IndexUsage'
order by i.index_id

--查询返回12行
select * from SalesOrderDetail_IndexUsage WHERE SalesOrderID=43659
--sys.dm_db_index_usage_stats结果
name    index_id    name    user_seeks    user_scans    user_lookups    user_updates
SalesOrderDetail_IndexUsage    0    NULL    0    0    1    0
SalesOrderDetail_IndexUsage    2    IX_SalesOrderID1    1    0    0    0

--更新影响12行
UPDATE SalesOrderDetail_IndexUsage 
SET LineTotal=LineTotal*1
WHERE SalesOrderID=43659
--sys.dm_db_index_usage_stats结果
name    index_id    name    user_seeks    user_scans    user_lookups    user_updates
SalesOrderDetail_IndexUsage    0    NULL    0    0    1    1
SalesOrderDetail_IndexUsage    2    IX_SalesOrderID1    2    0    0    1

--删除影响12行
DELETE from SalesOrderDetail_IndexUsage 
WHERE SalesOrderID=43659
--sys.dm_db_index_usage_stats结果
name    index_id    name    user_seeks    user_scans    user_lookups    user_updates
SalesOrderDetail_IndexUsage    0    NULL    0    0    1    2
SalesOrderDetail_IndexUsage    2    IX_SalesOrderID1    3    0    0    2

--插入12行
SET IDENTITY_INSERT dbo.SalesOrderDetail_IndexUsage on
INSERT INTO SalesOrderDetail_IndexUsage
(SalesOrderID,SalesOrderDetailID,CarrierTrackingNumber,OrderQty,ProductID,SpecialOfferID,UnitPrice,UnitPriceDiscount,LineTotal,rowguid,ModifiedDate)
select * from AdventureWorks2008R2.Sales.SalesOrderDetail
WHERE SalesOrderID=43659
SET IDENTITY_INSERT dbo.SalesOrderDetail_IndexUsage OFF
--sys.dm_db_index_usage_stats结果
name    index_id    name    user_seeks    user_scans    user_lookups    user_updates
SalesOrderDetail_IndexUsage    0    NULL    0    0    1    3
SalesOrderDetail_IndexUsage    2    IX_SalesOrderID1    3    0    0    3

--注意在sqlserver2012某些版本,重建索引会清空sys.dm_db_index_usage_stats中此索引的条目
ALTER INDEX IX_SalesOrderID1 ON SalesOrderDetail_IndexUsage REBUILD

-- Clean up
--DROP TABLE Test.dbo.SalesOrderDetail_IndexUsage
View Code

相关文章:

  • 2021-11-22
  • 2021-05-16
  • 2021-08-27
  • 2022-01-14
  • 2021-12-09
  • 2022-02-15
  • 2022-02-24
  • 2021-05-21
猜你喜欢
  • 2021-08-24
  • 2021-12-07
  • 2021-09-06
  • 2022-12-23
  • 2021-10-08
  • 2021-05-20
  • 2022-12-23
相关资源
相似解决方案