日期:2014-05-17  浏览次数:20442 次

优化代码或索引
环境:XP SP3+SQL2000
有一车间实时生产完工表FinishData,现大约30万行数据量,需要汇总一份报表,第一次查询约需2分钟,再刷可在10秒内响应完成,
查询代码如下:

Select Min(StartTime), Max(EndTime), SUM(UseTime) as ProUseTimes,SUM(StopTimes) as StopTimes,SUM(StopCount) as StopCount,
0, Count(*) as OrderCount ,0, Sum(TrimAreas) as TrimAreas, 
round(Sum((RWeight1+RWeight2+RWeight3+RWeight4+RWeight5+RWeight6+RWeight7)*TrimAreas/Areas),0) as TrimWeight, 
SUM(LenM) AS ProLen, SUM(Areas) AS ProArea, SUM(PassQTY)  AS ProQTY,
Sum(round((RWeight1+RWeight2+RWeight3+RWeight4+RWeight5+RWeight6+RWeight7)*(PassQTY+LossQTY)/OrderQTY,0)) as ProWeight,
SUM(Round(LossQTY*QlyLenMm/1000,0)) AS LossLen,SUM(LossAreas) AS LossArea,SUM(LossQTY) AS LossQTY, 
Round(Sum((RWeight1+RWeight2+RWeight3+RWeight4+RWeight5+RWeight6+RWeight7)*LossQTY/OrderQTY),0) as LossWeight, 
0, 0, 0, 0,
Sum(round(RWeight1*(PassQTY+LossQTY)/OrderQTY,0)) as DBCalWei, 
Sum(round((RWeight2+RWeight3)*(PassQTY+LossQTY)/OrderQTY,0)) as F1CalWei, 
Sum(round((RWeight4+RWeight5)*(PassQTY+LossQTY)/OrderQTY,0)) as F2CalWei, 
Sum(round((RWeight6+RWeight7)*(PassQTY+LossQTY)/OrderQTY,0)) as F3CalWei
FROM dbo.FinishData
Where WorkDate between '2013-1-1' and '2013-11-1' and WorkClass='C' and OrderQTY>0 and Areas>0

有对表WorkDate,WorkClass字段做索引。
请各位高手指教。

------解决方案--------------------
你可以用排除法看看是计算还是选取数据的时候最费时。把条件一一注释掉后再执行。
每次执行完语句后,运行
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
清除SQL Server 缓存

------解决方案--------------------
太多计算了,建议改用存储过来来实现了,查询速度肯定会提升的
------解决方案--------------------
我重新读了一下发现是30W数据,不好意思没仔细看。

你这个是统计查询,语句基本没有优化空间,不过可以用空间换时间的方法减少查询时间。。

你可以考虑定时运行语句把结果存到历史表中,报表直接按条件去历史表读取,或者用SSAS建个多维数据集用MDX语句读取,都可以大大加快读取速度,用秒级的时间完成读取。
------解决方案--------------------
引用:
重新试了一下:
无条件查询:耗时3分1秒
加索引(WorkClass,WorkDate,OrderQTY,Areas)带条件:2分22秒
执行计划:


看来加了索引,就算是加了where条件,效果也不太好,大部分开销都是在书签查找上了,看来是由于,你的查询,需要读出这个表里的大部分数据,而导致的很难优化。

像上面说的,把结果存储到一个历史表里面,到时候,直接取查询,这样速度会很快的,可以每天晚上,预先把结果存进去。