数据库环境:
WINDOWS2008R2
SQLSERVER2008R2
应用程序环境:
REDHAT6.5
TOMCAT
JAVA
一、故障现象
某系统应用查询超时
相关SQL:
SELECT v.OBarcode Barcode, v.CBarcode, v.ZID, v.FromName ZNAME, v.ItemName, v.Batch, v.OrderNo, v.SussDate createddate FROM V_TrackAllShipment v (NOLOCK) WHERE 1=1
AND v.OBARCODE = '13436135998'
其中V_TrackAllShipment是一个视图,且该视图里面还有一个视图,两个视图中均运用了大量的union(最多有9个)
该SQL在应用程序查询超时报错,无法得到查询结果,但直接在数据库中查询可以在几秒内得到查询结果,且结果返回只有几行数据
二、问题分析
1、尝试去掉1=1永真条件,查询依然超时
2、尝试去掉1=1永真条件,加上1<>1永假条件,几秒内查询成功,但返回结果为0行
3、尝试去掉所有的where条件,几秒内查询结果返回50行
三、使用profiler跟踪应用程序查询SQL
1、跟踪该SQL后,发现应用程序执行到数据库的SQL语句发生变化,如下:
SELECT top 50 v.OBarcode Barcode, v.CBarcode, v.ZID, v.FromName ZNAME, v.ItemName,
v.Batch, v.OrderNo, v.SussDate createddate
FROM V_TrackAllShipment v (NOLOCK) WHERE 1=1
AND v.OBARCODE = '13436135998'
多了top 50关键字
2、分析执行计划
带有top 50关键字的SQL执行计划,预估行数达到1亿多行,且索引失效
原SQL没有带top 50关键字的,预估行数只有几行
四、结论
应用程序在执行SQL的时候,向SQLSERVER数据库自动添加了top 50关键字,导致执行计划改变,查询超时
五、思考
为何去掉where条件后,查询结果在几秒内返回呢?原因在没有where条件的时候 top 50就只是根据一个ID 选择前面几个,但是有where 条件之后,top 50是先需要根据where条件进行查询出来之后,再把数据进行排序 然后top条数据
六、解决方案
1、在应用程序上去掉top 50
2、我尝试执行UPDATE STATISTICS dbo.tfacsalebarlib WITH FULLSCAN; 进行统计信息收集后,执行计划居然变正确了(该表是where条件那个字段对应所在的表)