根据在固态查询优化方面的经验,I/O等待是目前客户遇到的最常见等待。这其中有几个原因,I/O通常是数据处理操作最昂贵的资源。而且,当对查询或索引的设计或优化的不理想的情况下,会导致额外的I/O。此时,客户考虑计算机性能是,一般只考虑cpu和内存,而不会给I/O子系统足够的关注,数据库系统需要强健的I/O子系统。

  有些系统不必访问大部分数据,只对少数数据频繁访问。使用OLTP时通常是这种情况,它包含存储过程和查询只访问少量数据,但是调用频繁。在这种情况下,代码的编译和重新编译可能成为产生瓶颈的主要原因。OLTP系统涉及大量对少量数据的频繁修改,在这种情况下事务日志经常成为瓶颈。因为所有临时表的创建都是tempdb数据库中创建(无论是执行计划显式或者隐式创建),tempdb数据库可能成为非常严重的瓶颈。SQL Server经常使用tempdb执行其他操作。我们偶尔也发现存在并发及其其他问题。

  但是当我们根据SQL提供的等待信息内容太多,通过手动找出最关键的等待不是很方便。根据2-8原则,通常少量的等待占据了大部分等待时间。

  1:如下查询出累计值达到系统等待时间80%的重量级等待。

 1 --date:2013-5-13
 2 --DESC:sys.dm_os_wait_stats中,wait_time_ms表示所有进程在等待类型上的总等待时间,
 3 --    即使多个进程同时等待也计算在内。尽管如此,这些数字还是通常可以找到系统的主要问题域
 4 with waits
 5 as
 6 (
 7     select
 8     t.wait_type,
 9     t.wait_time_ms/1000 as wait_time_s,
10     100* t.wait_time_ms/SUM(t.wait_time_ms) over() as pct,
11     ROW_NUMBER() over(order by t.wait_time_ms desc) rn
12     from
13     sys.dm_os_wait_stats t
14     where t.wait_type not like '%SLEEP%' --过滤掉不相关的等待
15 )
16 select 
17 t.wait_type,
18 CAST(t.wait_time_s as decimal(12,2)) as wait_time_s,
19 CAST(t.pct as decimal(12,2)) as pct,
20 CAST(SUM(t1.pct) as decimal(12,2)) as running_pct
21 from
22 waits t
23 inner join waits t1 on t1.rn<=t.rn
24 group by t.rn,t.wait_type,t.wait_time_s,t.pct
25 having SUM(t1.pct)-t.pct<80 --百分比临界值
26 order by t.rn

  2:将保存的信息保存到临时表中,进行分析。定时更新(例如每一个小时一次)。这样可以分析中一天等待的分布,找出高峰值。

 1 --DESC:创建表结构
 2 use databaseName
 3 go
 4 
 5 if OBJECT_ID('WaitStats') is not null 
 6     drop table waitStats;
 7 go
 8 
 9 select 
10 GETDATE() as dt,
11 t.wait_type,
12 t.waiting_tasks_count,
13 t.wait_time_ms,
14 t.max_wait_time_ms,
15 t.signal_wait_time_ms
16 
17 into waitStats
18 from
19 sys.dm_os_wait_stats t
20 where 1=2 --创建框架

  定时插入数据到状态表中。提醒wait_time_ms是累计值

 1 --DESC:定时插入数据到状态表中
 2 insert into waitStats
 3 select 
 4 GETDATE() as dt,
 5 t.wait_type,
 6 t.waiting_tasks_count,
 7 t.wait_time_ms,
 8 t.max_wait_time_ms,
 9 t.signal_wait_time_ms
10 from
11 sys.dm_os_wait_stats t;

  根据时间段条件,查询出此时间段内等待类型,等待时间。提供dba分析系统资料

 1 if OBJECT_ID('fn_inteval_waits') is not null 
 2     drop function fn_inteval_waits
 3 go
 4 --date:2013-5-14
 5 --DESC:根据开始时间和截止时间查询等待类型等待你时间的长度
 6 create function fn_inteval_waits
 7 (@fromdt datetime,@todt datetime)
 8 returns table
 9 as
10 return
11 with Waits as
12 (
13     select 
14     dt,wait_type,wait_time_ms,
15     row_number() over (partition by wait_type order by dt)as rn
16     from
17     WaitStats w
18     where dt>=@fromdt and dt<@todt+1
19 )
20 select prv.wait_type,prv.dt as starttime,
21        CAST((cur.wait_time_ms-prv.wait_time_ms)/1000 as decimal(12,2)) as interval_wait_s
22 from
23 Waits as cur
24 inner join Waits prv
25 on cur.wait_type=prv.wait_type  and cur.rn=prv.rn+1
26 and prv.dt<=@todt
27 go
28 
29 
30 select t.wait_type,t.starttime,t.interval_wait_s
31 from
32 fn_inteval_waits('2013-5-13','2013-5-15') as t
33 order by sum(interval_wait_s) over (partition by wait_type) desc,
34 t.wait_type,t.starttime

 

 

posted on 2013-05-13 12:30  代岳强  阅读(572)  评论(0编辑  收藏  举报