最近公司的系统优化了很多SQL代码,确实想写的点东西分享一下就写到这里来了。
方法一
方法二
用户经常抱怨的功能重点优化。
方法三
可以使用以下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
首先可以打开实际执行的执行计划,看一下到底是哪一段慢,然后针对慢的代码进行优化。优化的方向可以有以下:
语法优化
也就是常说的避免使用<>,where 后面跟函数、避免使用or等会引起索引失效的操作,select出用的字段而不是select*等。
缩小查询范围
对于有限制条件的可以先用筛选出数据写进临时表再去做关联、计算等。
频繁关联的表先筛选后写进临时表。
对于一些大表的查询可以加上with (nolock)避免锁表。
代码逻辑优化
梳理逻辑,重新编写。
我们定位到慢的语句如下,显示实际执行计划如下:
可以发现,两分半钟基本都是消耗在查询 2 上,占总批:100%。我们再分析查询 2,
单独对这几个表查询都并没有消耗很久的时间,分析查询 2 的执行计划,可以发现基本都是消耗在这个嵌套的循环,left outer join 上,而这个left outer join 所有执行的实际行数是1W4,而估计执行到了8300多万,猜测是由于右表又join,导致了这个嵌套的循环查询的数据量翻了N倍。
于是我尝试先将数据写进临时表,再去关联查询。
修改后查询只用了一秒,因此大家在写查询的时候,应:
尽量避免右表再join右表!
尽量避免右表再join右表!
尽量避免右表再join右表!
由于是半吊子水平的SQL 在不断的尝试猜测下去修改代码进行优化。