SQL存储过程的优化

SQL存储过程的优化

最近公司的系统优化了很多SQL代码,确实想写的点东西分享一下就写到这里来了。

查找慢的SQL

  • 方法一

    首先通过SQL Server自带的报表《查看对象执行统计信息》查看CPU平均时间靠前的对象,重点优化这些对象。
    SQL存储过程的优化_第1张图片

  • 方法二
    用户经常抱怨的功能重点优化。

  • 方法三

    可以使用以下SQL没事查一查,优化经常出现的执行时间比较久的SQL。

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    SELECT [Spid] = session_id, start_time
    	, datediff(s, start_time, getdate()) AS runtime
    	, Program = program_name, ecid
    	, [Database] = DB_NAME(sp.dbid)
    	, [User] = nt_username, [Status] = er.status
    	, [Wait] = wait_type
    	, [Individual Query] = SUBSTRING(qt.text, er.statement_start_offset / 2,
    	 (CASE 
    		WHEN er.statement_end_offset = -1 
    			THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2
    		ELSE 
    			er.statement_end_offset
    	END 
    	- er.statement_start_offset) / 2)
    	, [Parent Query] = qt.text, hostname, nt_domain
    FROM sys.dm_exec_requests er
    	INNER JOIN sys.sysprocesses sp ON er.session_id = sp.spid
    	CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) qt
    WHERE session_id > 50
    	AND session_id NOT IN (@@SPID)
    ORDER BY 8
    
    

优化思路

首先可以打开实际执行的执行计划,看一下到底是哪一段慢,然后针对慢的代码进行优化。优化的方向可以有以下:

  1. 语法优化
    也就是常说的避免使用<>,where 后面跟函数、避免使用or等会引起索引失效的操作,select出用的字段而不是select*等。

  2. 缩小查询范围
    对于有限制条件的可以先用筛选出数据写进临时表再去做关联、计算等。
    频繁关联的表先筛选后写进临时表。
    对于一些大表的查询可以加上with (nolock)避免锁表。

  3. 代码逻辑优化
    梳理逻辑,重新编写。

执行优化

我们定位到慢的语句如下,显示实际执行计划如下:
SQL存储过程的优化_第2张图片
可以发现,两分半钟基本都是消耗在查询 2 上,占总批:100%。我们再分析查询 2,
单独对这几个表查询都并没有消耗很久的时间,分析查询 2 的执行计划,可以发现基本都是消耗在这个嵌套的循环,left outer join 上,而这个left outer join 所有执行的实际行数是1W4,而估计执行到了8300多万,猜测是由于右表又join,导致了这个嵌套的循环查询的数据量翻了N倍。
SQL存储过程的优化_第3张图片
于是我尝试先将数据写进临时表,再去关联查询。
SQL存储过程的优化_第4张图片
修改后查询只用了一秒,因此大家在写查询的时候,应:
尽量避免右表再join右表!
尽量避免右表再join右表!
尽量避免右表再join右表!

最后

由于是半吊子水平的SQL 在不断的尝试猜测下去修改代码进行优化。

你可能感兴趣的:(sql,sqlserver,数据库)