您的位置:首页 > 数据库

SQLServer性能优化一则小实例(2010-07-22)

2010-07-22 22:30 155 查看
今天下午优化了一个存储过程,通过sys.dm_exec_query_stats和sys.dm_exec_sql_text() 定位到的,发现运行次数虽然很少,但是每次却长达上千万毫秒的cpu消耗,但实际执行虽然时间比较久,却也不过几十分钟而已,不知道是不是SQLServer系统性能视图的缺陷。

既然有问题那就找吧

这是一个存储过程,类似于

create procedure sp_exec_task

as

declare cursor cur_test for select * from tableA

begin

open cur_test

fetch cur_test into ...

WHILE @@FETCH_STATUS=0

BEGIN

if true

update tableB where id=tableA.id and other_cond

else

update tableB where id=tableA.id and other_cond

if true

update tableC where id=tableA.id and other_cond

else

update tableC where id=tableA.id and other_cond

fetch cur_test into ...

end

CLOSE cur_test

DEALLOCATE cur_test

end

怎么分析呢?

1、开始的时候是让游标空循环,发现一共1万多条记录,空循环时间基本为0

2、再次把所有的DML语句转化为SELECT,并记录每个步骤的运行时间和一次完整游标的循环时间

最后循环中变为

BEGIN

print 'step 1'+convert(varchar,109,getdate()

select * from tableB where id=tableA.id and other_cond

print 'step 1'+convert(varchar,109,getdate()

select * from tableC where id=tableA.id and other_cond

END

通过上百次的循环测试,发现每次循环大概需要60毫秒,100次的花就是6秒,10000次可不就是10分钟

3、检查了一下游标循环中用的表和where条件,发现选择性不错,就添加索引,再次安装上面的办法进行测试

这次是单次循环0~1毫秒,100次大概是1秒,10000次还是需要1分多钟的

4、1分多钟是可以忍受的,干脆直接测完吧,运行过程中,不断发现内存消耗极大,很快居然耗光了内存

5、添加了SET NOCOUNT ON之类的,运行后还是内存暴增

6、后来思考了一下是不是select * from tableB的不断刷新导致的,直接修改为

select top 1 @tt=tt from tableB where id=tableA.id and other_cond

这样就不会持续刷新屏幕了

7、运行后,果然只需要短短的4秒钟。

总结:

其实在数据库中与性能相关的,无论是耗cpu还是耗内存还是耗硬盘还是锁的问题,分析到最后,95%以上都与SQL和索引相关

首先要找到问题,才能谈到分析问题,分析问题就在于多实践,而实践在于尽量屏蔽与问题无关的外界因素。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: