上文说道了失效效应。只想说明在Performance Tunning方面只能根据情况来寻求原因并解决。这是一 个有意思的过程。大原则是经验,帮助我们少犯错误。因此,糟糕的设计,必然导致性能问题。没有经验 的程序员必然会写出糟糕的代码。但是良好的设计可以弥补程序员的经验不足。这个到此打住,这个 topic涉及品质管理,实在太大了。
再看一例,失效效应的体现。
还是上文数说道了2种SQL文 写法产生的执行计划。我选用一台双核的PC,相当于2个单核CPU。
有一个大表TB_CWB。记录约30 -40万。(在生产环境下属于小数据量,在我的测试中可以看成大表)。表上已经对fn_Clt_Datetime 做 了索引。
1.SQL文一
select CWB_No,fn_Clt_Datetime,acctId_guid,fn_OrigZone_Id,DestSZMCode,DestZone_Id,CWBType,fn_Clt_Dat etime,fn_cwbtype,
PayType,Payweight,StdPriceweight,StdFreight,IsCalculated,AFterDsctFreight,
SchgFreight,InvcFreight,Salesamount,SchgDetail,SchgFreight_Remarks
from OCS_TB_CWB
WHERE
fn_Clt_Datetime between '2008-9-1' and '2008 -9-16'
运行结果,发现奇慢无比。需要12秒才能出结果。
检查执行计划,发 现用了聚集索引扫描(主键),就是相当于选择了全表扫描的计划。因为CBO认为这句SQL比动用索引还要 快。见下图
2 SQL文二
存储过程写法
declare @date_from datetime
declare @date_to datetime
set @date_from='2008-9-1'
set @date_to='2008-9-16'
select CWB_No,fn_Clt_Datetime,acctId_guid,fn_OrigZone_Id,DestSZMCode,DestZone_Id,CWBType,fn_Clt_Dat etime,fn_cwbtype,
PayType,Payweight,StdPriceweight,StdFreight,IsCalculated,AFterDsctFreight,
SchgFreight,InvcFreight,Salesamount,SchgDetail,SchgFreight_Remarks
from OCS_TB_CWB
WHERE
fn_Clt_Datetime between @date_from and @date_to
速度也慢。第一次16 秒(比全表扫描还慢?有可能),第二次9秒,这还像点话。但是上面SQL文一再执行一遍,也差不多9秒。
说明这2种写法在这里情况下大致都差不多。
第2种写法的执行计划。非常肯定用到了索引 。在这里我基本倾向于涉及查询之类的,用存储过程,CBO失效认为全表扫描比索引代价小的可能性低。
3 SQL文 三
对于SQL文一,强制用索引。
--检查价格计算结果
select CWB_No,fn_Clt_Datetime,acctId_guid,fn_OrigZone_Id,DestSZMCode,DestZone_Id,CWBType,fn_Clt_Dat etime,fn_cwbtype,
PayType,Payweight,StdPriceweight,StdFreight,IsCalculated,AFterDsctFreight,
SchgFreight,InvcFreight,Salesamount,SchgDetail,SchgFreight_Remarks
from OCS_TB_CWB
WITH (index(IND_FN_CLT_DATETIME_OF_OCS_TB_CWB))
WHERE
fn_Clt_Datetime between '2008-9-1' and '2008-9-16'
运行0秒,天哪,不会吧。赶快看执行计 划
执行 计划不经用了索引,还动用了并行装载数据。为了公平期间,反复运行几次,最慢4秒,基本1秒。
在这个案例中。指定值的SQL在CBO看来还不如全表扫描(估计因为是它已经知道你要找的值,根 据数据分布,发现摸一次索引树的代价还不如全表扫描更快)。呵呵,但是你强制指定索引,它决定把2 个cpu都用上来帮助你获得最佳性能。
结果成了在这个case中的最佳结果。
不过,在大部 分情况下,我个人认为SP的写法还是比较好的选择。parse参数的方法(sp_executesql)只有当只变化参 数值,可以重用第一次的执行计划。但是并一定说SQL Server给你的执行计划就是好的。
总结一 下,
1)这个case告诉我们,你建了索引也不会快,因为SQL Server的CBO会决定不用,这还是和 SQL文有关系。
2)硬件强也要看SQL Server是不是考虑用Paralism,而不好的SQL文反而会让CBO的 失效效应出现差的结果。
3)而最后一个case,但是有点对失效效应的利用的意味,让你把硬件充 分发挥出来,倒是有点出奇制胜的效果了。
4)回到正题,良好的设计和代码控制,才是性能好的 根本保证。而有很多项目组很忽视数据库设计review和代码review,是出现性能问题的根本原因。好的品 质不是靠测试和后期强人tunning出来的,而是靠良好的设计和管理管出来的。
ASP编码教程:如何实现/使用缓存
[ASP]2015年4月15日ASP编码教程:asp缓存的分类
[ASP]2015年4月15日ASP编码教程:何谓ASP缓存/为什么要缓存
[ASP]2015年4月15日ASP编码教程:asp实现的sha1加密解密代码
[ASP]2015年4月15日ASP编码教程:asp执行带参数的sql语句实例
[ASP]2015年4月14日