由于工作中接触存储过程比较多点,在这里大概记录下怎么解决一些常见的问题
当运行一个逻辑比较复杂的存储过程,然后发现停在那里结束不了的情况,那么基本上是卡死在某一句话了,这个时候我们可以使用微软提供的sql server profiler来进行跟踪,
看到底是哪句话那么慢了。
正常来说设置跟踪如下2种就可以了
1.在处理数据量比较多的时候,要确认我们处理数据的范围,是否在满足逻辑的情况下能缩小到最小。如果取了10W条数据,但是只有5W条我们要使用,那就没必要了,
所以要分析逻辑,进行优化。
2.在任何语句里面最好不要调用别的计算函数,因为函数需要一行行进行运行,会大大降低效率,如果有必要使用计算结果进行处理的话,最好能在单表里面就处理好,在
后面进行使用
3.当需要查询A表里面但是在B表里面不存在或存在的数据时,如果使用exists方法时,比如select 1 from A a where exists(select 1 from B where ID=a.ID(或条件比较复杂))
当B表比较大时,需要对用到的条件建立索引,这样能提高效率,不然可能就是表扫描。
4.在对数据库中的业务大表进行大数据查询时,如果所要求的数据不是特别实时的话,可以用上with(nolock),有比较好的效率提升。
5.创建表的主键时,如果不是特别需要,使用int类型要好于使用uniqueidentifier类型
6.当在SP中发现一句insert into select比较慢时,可以单独看是select比较慢还是insert比较慢,如果select不慢但是insert慢时,要考虑是不是在插入数据时对某些索引进行了维护导致的,而这些索引又是可有可无的,比如如果用的是NewID()这种基本上不会重复的主键,考虑是否可以去除主键。
7.在处理一句话时,如果效果不是很好,可以试试看能否把这句话转成多句执行。比如2张表要查询,但是有的条件不是索引字段,这个时候转换思路,先最大化应用索引,得到主键ID的信息(一般表都会有主键的索引的),然后通过主键临时表取查询想要得到的东西,这个时候范围已经通过主键缩小了。
8.同一句话在查询分析器里面执行与在SP里面执行可能最终的执行计划会不一样,最好能看下实际的执行计划,在执行计划中查看【实际行数】时,如果行数与子查询得到的数目有明显的差异,那么可以考虑将子查询替换成临时表。
9.Inner join ,in,exists区别。当B表数据比较少时用in的效果比较好。数据多考虑使用inner join或exists具体可以看执行计划。
一些常用查询
--查看某个进程的执行状态
select cmd,PROGRAM_NAME,* from sys.sysprocesses where spid=65