5、还是运行SQL Server Profiler,将运行结果保存到某个库的新表中(随便起个名字系统会自己建)。让它运行一段时间,然后可以用
select top 100 * from test where textdata is not null order by duration desc
这个可以选出运行时间长的语句,在ORDER BY 中可以替换成CPU、READS,来选出CPU占用时间长和读数据过多的语句。
定位出问题的语句之后就可以具体分析了。有些语句在执行计划中很明显可以看出问题所在。
常见的有没有建索引或索引建立不合理,会出现table scan或index scan,凡是看到SCAN,就意味着会做全表或全索引扫描,这是带来的必然是读次数过多。我们期望看到的是seek或键查找。
7、如何优化单个部分,一个复杂的SQL语句,SQL SERVER会很聪明地重组WHERE后的语句,试图匹配索引。选中带优化的步骤,选择旁边的‘属性”,再选择其中的“谓词”,将其中部分复制下来,这部分就是分解后的WHERE 语句,然后在查询界面中select * from 表 where 刚才复制下来的“谓词”。这个就是需要优化的部分,既然已经走到这一步了,大部分人应该能手动建立索引了,因为这里的WHERE语句比之前的肯定简单不少。(在我项目中原始SELECT语句的WHERE部分有10个条件组合,涉及6个字段,提取出来要优化的部分就4个条件,涉及到3个字段。新的索引建立后,CPU占用率一下子就降低了,而且新建立的索引涉及的字段属于不常UPDATE的部分,频繁的读写操作不会影响UPDATE的效率)
8、以上就是优化的思路,最后提一些优化过程或是系统设计时中需要注意的问题。
A、尽量避免用select * from xxx where abc like '%xxx'类型的模糊查询,因为%在前面的话是无法利用到索引,必然会引起全量SCAN操作。应该找寻替代方式或用前置条件语句把like查找之前的行数减到最低。
B、尽量避免对大表数据进行select top n * from xxx where xxxx order by newid()的取随机记录的操作。newid()操作会读全量数据后再排序。也会占用大量CPU和读操作。可以考虑用RAND()函数来实现,这方面我还在研究中,对于整表操作比较好弄,比如id>=(select max(id) from table)*rand()。但如果取局部数据的随机记录还需要思量。
C、在SQL Server Profiler记录中会看到Audit Logout会占用大量CPU和读写等操作。查了一些资料称是某个链接在某次连接过程中执行SQL语句产生的总数,不用过于担心。看下来的确似乎这样,很多Audit Logout的CPU和IO消耗量和之前优化的语句基本一致。所以在第5点我提的SQL语句用textdata is not null条件把Audit Logout给隐去。
D、两个不同字段OR语句会导致全表扫描。例如 where m=1 or n=1。如果建立一个索引是m和n,同样会引起scan,解决方法是给m和n分别建立索引。测试12万条数据的表,索引建立错误的情况下IO开销高达 10.xxx,分别建立索引后,全部变成0.003,这个反差是非常巨大的。虽然会引起INSERT操作的性能问题,但毕竟大部分瓶颈在SELECT的读操作上。
E、索引查找(Index Seek)和索引扫描(Index Scan),我们需要的是前者,而引起后者的原因通常是某个索引里的字段多余要查找的,例如索引建立在A和B两个字段,而我们只要查找A,则会导致 INDEX SCAN。建议针对单独的A建立索引,以形成索引查找。
F、对于小表不建议建立索引,特别是几百的数据量,只有上千上万级别的数据建立索引才有效果。