一次SQL优化

前不久一位同事在做两个表关联更新,等了N久没执行出来,找我帮他看是什么原因。他的更新语句如下

update dsamerr201109 a

set (a.opr_status, a.new_result, a.unique_no6, a.unique_no7, renew_time)= (select '1',

note_info,

function_attr5,

function_attr6,

sysdateup_date

from dmcs.edmcsattributeday_suess b

where b.collect_day =

'20110919'

and b.renew_flag = '1'

and a.id = to_char(b.stream_id))

执行计划

update

indexfullscan ind_dsamerr201109

table access full edmcsattributeday_suess

他在a表的id字段上建了一个索引,但是我看执行计划并没有走索引,我在update后面加上index hint后,还是没有变化,任然没有走索引,后面在网上搜索了一下,查阅了相关的资料,发现是因为建表时id字段设置的是允许为空(nullable)的,这样会导致索引失效,修改为不为空后,执行计划发生了变化

出现了索引全扫描,但是任然是等待N久也没法更新完成,分析是因为这个索引全扫描会有回表操作,跟之前的执行效果差不多,仔细分析他的SQL语句后,发现他的SQL存在问题,对关联不上的记录会被置空,我在最后加上了一句

where exists(select 1 fromdmcs.edmcsattributeday_suess c where a.id=to_char(c.stream_id))

执行计划

update

nested loop

sort unique

table aceess full edmcsattributeday_suess

index range scan dsamerr201109
table access full edmcsattributeday_suess

再看执行计划发生了明显变化,对A表执行的是索引范围扫描了,执行成本和IO都得到了大幅下降执行效果也证实了这一点,仅用0.09s就完成了update。

总结

1、 建索引的字段不能设置为nullable,否则不会走索引

2、 索引全扫描的回表操作会导致性能下降

3、 编写SQL语句时要仔细分析,尤其是多表的连接操作



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值