春节后上了一个新项目,不料很快就遇到了严重的性能问题,好在有高手相助总算及时的解决了,我也跟着学了不少方法,在这里拿出来跟大家分享下,说得不对的地方尽管拍砖过来。
假定你已经基本了解了索引的类型和工作原理、SQL执行计划、逻辑读/物理读等概念、以及掌握了Perfmon和SQL Profiler等工具。
关于性能的故事,一般都是从用户抱怨慢开始的。DBA执行了下sp_who2 active,居然发现一大堆的blkby。找到源头,杀之。然而很快另一个又冒了出来。好了,等着BOSS发来贺电吧。
在数据服务器活动结点上打开perfmon,CPU偏高但尚可,基本在70%左右,而且没有被焊在100%不下来的状况,但是内存Pages/sec和平均磁盘队列都活跃得有点异常,而且数值相当高。
打开SQL Profiler,抓取Duration超过2000的语句。一般我选择的事件是SP:StmtCompleted和SQL:BatchCompleted以及SQL:StmtCompleted。
果然,发现有一句语句Duration时间比较长,而且频繁出现。仔细检查发现是属于某个存储过程的一个子查询,居然没有where条件,直接按照它做的话会返回22万条记录!询问开发人员得知可以加上某些条件,于是紧急加上限制条件,这个字段本来就有索引的,因此这句语句就算暂时解决了。
还有一句语句与此情况类似,但已有条件,可是在查询分析器里执行,返回了将近10万条记录,显然又是一个不必要的操作。再次询问开发人员,他的第一反应是不可能,说只要返回一条就够,而且语句中也加了top 1的。
但按Ctrl L看了下执行计划,发现TOP是最后一步做的,而且在Profiler里也确实没有找到TOP的字样,怀疑内部执行的时候还是按10万条在做。紧急解决的办法是再AND一个日期字段,只查大于最近24小时的。也给它们加上索引。暂时解决,但对于TOP的具体工作方式还是存疑。如果我们想得都属实的话,TOP绝对也算一个大陷阱了。