记一次SQL语句执行性能调优

问题描述:

今天在解决项目上面的一个问题是。遇到一个非常奇怪的问题:
如下的sql语句


SELECT COUNT
	( * ) AS totalnum 
FROM
	requestbase r 
WHERE
	EXISTS (
	SELECT
		1 
	FROM
		requestlog wl 
	WHERE
		wl.requestid= r.id 
		AND wl.logtype NOT IN ( '402881e50c5b4646010c5b5afd170009', '402881e50c5b4646010c5b5afd17000e' ) 
		AND wl.operator = 'HRMRESOURCEECOLOGYAAAA0000000009' 
	) 
	AND r.isdelete= '0'

只是wl.operator = ‘HRMRESOURCEECOLOGYAAAA0000000009’ 的条件不同,执行时间却相差超级多。

问题原因:

通过查阅资料,分析不同条件下的sql执行计划:
以下是执行时间较短的执行计划:
记一次SQL语句执行性能调优_第1张图片
以下是执行时间较长的:

记一次SQL语句执行性能调优_第2张图片
只是ID不一样,但是其执行计划却不一样。
而图二使用了Clustered Index Seek(聚集索引查找),理论上效率应该更高才对。但是此处估计是因为requestbase 表中的数据量比较多(有40多万条),直接使用其聚集索引查找反而效率不如第一个执行计划,第一个执行计划通过 requestlog 的logtype索引将其先限制住。

解决方法:

利用查询提示(Hint)引导语句执行,此处使用的是 OPTIMIZE FOR 提示,引导语句按照相应ID的执行计划执行。
但是个人觉得要慎用。

DECLARE  @test NVARCHAR(50)
SET @test='8aa0a19e4c226cbc014c253544ce07cd'
SELECT COUNT
	( * ) AS totalnum 
FROM
	requestbase r 
WHERE
	EXISTS (
	SELECT
		1 
	FROM
		requestlog wl 
	WHERE
		wl.requestid= r.id 
		AND wl.logtype NOT IN ( '402881e50c5b4646010c5b5afd170009', '402881e50c5b4646010c5b5afd17000e' ) 
		AND wl.operator = '8aa0a19e4c226cbc014c253544ce07cd'--'8aa0a19e635e5560016367f40ac106b9'
	) 
	AND r.isdelete= '0'
	OPTION(OPTIMIZE FOR(@test='HRMRESOURCEECOLOGYAAAA0000000009'))
	



遗留问题:

1.requestlog这张表的数据量同样不少?为什么这样的执行计划执行效率高那么多?
2.有没有可能从语句执行上面进行优化?
本人试过使用如下的sql语句进行替换,本以为语句能有稍稍有些优化,但实际效果竟然比上述的语句还要慢200ms左右。
权且留作后续分析吧。

select count(*) from requestbase r , requestlog r1
where
 r.id = r1.requestid
and r.ISDELETE = '0'
and r1.operator = 'HRMRESOURCEECOLOGYAAAA0000000004'
and r1.logtype <> '402881e50c5b4646010c5b5afd170009'
and r1.logtype <> '402881e50c5b4646010c5b5afd17000e'









参考:
SQL Server调优系列玩转篇
如何看懂SQL SERVER执行计划

你可能感兴趣的:(JAVA基础,数据库)