|
几个建议
有好几年没具体写SQL,还真有点落伍了,几点建议,估计会有错,希望有一条两条对你有启发,就不要拿板砖砸我。不行我就只要换马甲了。
SELECT LEFT(pres_date, 6) as name, sum(cast(substring(anal_result, 1, 1) as int)) as pwjj, sum(cast(substring(anal_result, 2, 1) as int)) as xhzy,
sum(cast(substring(anal_result, 4, 1) as int)) as cfyy, sum(cast(substring(anal_result, 5, 1) as int)) as kss, sum(cast(substring(anal_result, 7, 1) as int)) as qtwt,
sum(cast(substring(anal_result, 8, 1) as int)) as yywt, sum(cast(substring(anal_result, 1, 1) as int)) +sum(cast(substring(anal_result, 2, 1) as int))
+sum(cast(substring(anal_result, 4, 1) as int)) +sum(cast(substring(anal_result, 5, 1) as int)) +sum(cast(substring(anal_result, 7, 1) as int))
+sum(cast(substring(anal_result, 8, 1) as int)) as count
FROM t_pres_info
WHERE (LEFT(pres_date, 8) >= '20090610'
AND LEFT(pres_date, 8) < '20090612'
AND len(rtrim(ltrim(pres_date))) = 14)
group by LEFT(pres_date, 6)
order by LEFT(pres_date, 6)
在这里,WHERE 中有任何计算都是非常费事的,而且千万条数据每个算一遍,又丢掉,太浪费了。
1)pres_date 是否该用日期,而不用字符串?比较日期数据,一个CPU运算,字符串至少要8次,还要加上LEFT。
2)非要用字符串,可否对原表Table做一个View,然后建一个index,在MS SQL 2005以后,就叫Persistant View, 就是系统给你算一遍后,会存在物理内存里,就好像你有个真的Table,你做1000次 SELECT,LEFT运算只算一次。
3)如果经常计算,可否为统计性的数据做一个其他的查询库,和你的生产库分离?同时可以用分区方式减少单元数据条数,比如2009年一个,2008年一个,2007年一个。
4)(这个方法有点不确定),LEFT(pres_date, 8) >= '20090610' 能不能改成 pres_date >= '20090610000000'?也许会快点。
5)(这个更不确定),如果你用个嵌套SQL,先将所有想要的表列原样查询到一个变量,再在结果中运算,会不会有帮助?(这里不确定的是,如果这在存储过程中,也许编译器已经优化成这样了)
SELECT LEFT(pres_date, 6) as name, sum(cast(substring(anal_result, 1, 1) as int)) as pwjj, sum(cast(substring(anal_result, 2, 1) as int)) as xhzy,
sum(cast(substring(anal_result, 4, 1) as int)) as cfyy, sum(cast(substring(anal_result, 5, 1) as int)) as kss, sum(cast(substring(anal_result, 7, 1) as int)) as qtwt,
sum(cast(substring(anal_result, 8, 1) as int)) as yywt, sum(cast(substring(anal_result, 1, 1) as int)) +sum(cast(substring(anal_result, 2, 1) as int))
+sum(cast(substring(anal_result, 4, 1) as int)) +sum(cast(substring(anal_result, 5, 1) as int)) +sum(cast(substring(anal_result, 7, 1) as int))
+sum(cast(substring(anal_result, 8, 1) as int)) as count
FROM
{
select anal_result from t_pres_info
WHERE (LEFT(pres_date, 8) >= '20090610'
AND LEFT(pres_date, 8) < '20090612'
AND len(rtrim(ltrim(pres_date))) = 14)
}As MySmallerTable
group by LEFT(pres_date, 6)
order by LEFT(pres_date, 6)
这里有几个好处:
a) 你尽快的查完了t_pres_info表,这样尽量不影响其他查询。
b) 你做的许多工作其实都只用到anal_result,MySamllertable只要这一列,同时只有两天的数据,这样临时变量表会不会小点?
总体觉得,你如果能把上述所有的字符串运算(LEFT,Cast, Substring, ltrim, rtrim) 都剪掉,性能能至少能提高10倍.
[ 本帖最后由 PromisingChina 于 2009-6-12 19:54 编辑 ] |
|