日期:2014-05-18  浏览次数:20681 次

这个“存储过程”应该怎样优化
这个“存储过程”应该怎样优化???
执行时间为“20秒”,目标要控制在“5秒”以内,表(WarnUseEnergy)中的数据量有“200多万”。


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER proc [dbo].[NSP_GetWarnTop10]
@MeterType char(4)
as

select top 10 COUNT(wue.MeterNo) as num,(m.MeterName+'('+RTRIM(wue.MeterNo)+')') as MeterNN,(r.RegionName+' '+(ISNULL(b.BuildingName,''))) as RegionBuilding from WarnUseEnergy wue left join Meter m on wue.MeterNo=m.MeterNo left join BuildingMeterRef bmr on wue.MeterNo=bmr.MeterNo left join Building b on bmr.BuildingNo=b.BuildingName left join RegionMeterRef rmr on wue.MeterNo=rmr.MeterNo left join Region r on rmr.RegionNo=r.RegionNo where wue.MeterType=@MeterType group by wue.MeterNo,m.MeterName,b.BuildingName,r.RegionName order by num desc

应该怎样优化,减少运算。。。

------解决方案--------------------
SQL code

select top 10 
COUNT(wue.MeterNo) as num,
(m.MeterName+'('+RTRIM(wue.MeterNo)+')') as MeterNN,
(r.RegionName+' '+(ISNULL(b.BuildingName,''))) as RegionBuilding 
from WarnUseEnergy wue 
left join Meter m 
on wue.MeterNo=m.MeterNo 
left join BuildingMeterRef bmr 
on wue.MeterNo=bmr.MeterNo 
left join Building b 
on bmr.BuildingNo=b.BuildingName 
left join RegionMeterRef rmr 
on wue.MeterNo=rmr.MeterNo 
left join Region r 
on rmr.RegionNo=r.RegionNo 
where wue.MeterType=@MeterType 
group by wue.MeterNo,m.MeterName,b.BuildingName,r.RegionName 
order by num desc

--这么多left join ,用临时表或者试图吧
从你的语句上来说算法一点都不复杂

------解决方案--------------------
你这几个表,每个表大约有多少数据?

正常索引建好了200万数据1秒内是可以搞定的。

但是如果是多表连接查询就不同了,要看各表的数据量,和条件字段的索引等情况。
------解决方案--------------------
儘量使用INNER JOIN 
在 WarnUseEnergy表上 建立複合索引 , (MeterNo,MeterType) 按這個順序.
SQL code

CREATE NONCLUSTERED INDEX WarnUseEnergy_MeterNo_MeterType ON WarnUseEnergy(MeterNo,MeterType)

------解决方案--------------------
儘量使用INNER JOIN 
在 WarnUseEnergy表上 建立複合索引 , (MeterNo,MeterType) 按這個順序.
SQL code

CREATE NONCLUSTERED INDEX WarnUseEnergy_MeterNo_MeterType ON WarnUseEnergy(MeterNo,MeterType)

------解决方案--------------------
Inner Join 只會保留相匹配的數據 
Left Join 會保留左表完整的數據
同理Right Join 會保留右表完整的數據

使用Left Join,這樣你WarnUseEnergy某些匹配不上的數據也會保留在結果裏面,導致執行速度過慢.
------解决方案--------------------
SQL code

select top 10  
COUNT(wue.MeterNo) as num,
(m.MeterName+'('+RTRIM(wue.MeterNo)+')') as MeterNN,
(r.RegionName+' '+(ISNULL(b.BuildingName,''))) as RegionBuilding  
from [color=#FF0000](select * from WarnUseEnergy where wue.MeterType=@MeterType ) [/color]wue  
left join Meter m  
on wue.MeterNo=m.MeterNo  
left join BuildingMeterRef bmr  
on wue.MeterNo=bmr.MeterNo  
left join Building b  
on bmr.BuildingNo=b.BuildingName  
left join RegionMeterRef rmr  
on wue.MeterNo=rmr.MeterNo  
left join Region r  
on rmr.RegionNo=r.RegionNo  
  
group by wue.MeterNo,m.MeterName,b.BuildingName,r.RegionName  
order by num desc

------解决方案--------------------
题外话:最后一句‘order by num desc’是错的吧
------解决方案--------------------
提高效率的一般做法是用空间换时间
你把你要提取表的数据,都放到临时表里面,也就是MeterType=@MeterType 的时候的MeterNo都符合的数据,然后再把临时表left join。
这样子临时表的数据会少很多,left join的时候速度也会快很多
------解决方案--------------------
临时表一方面数据量少,另一方面是你独占的,所以查询速度会很快
我曾经做过一个存储过程执行要2小时,用临时表后只需要半小时