oracle update 效率低 怎么办呢

create or replace procedure P_CRM_UPDATE_VIP_CARD_STATE AS

CURSOR CC IS
SELECT A.SERIAL_NUMBER,
A.REMOVE_TAG,
A.VIP_CARD_END_DATE
FROM TF_F_CUST_VIP A
WHERE A.REMOVE_TAG = '0'
AND A.VIP_CARD_END_DATE < SYSDATE;
CCREC CC%ROWTYPE;
BEGIN
OPEN CC ;
LOOP
FETCH CC
INTO CCREC;
EXIT WHEN CC%NOTFOUND;

UPDATE TF_F_CUST_VIP
SET VIP_CARD_STATE = '4'
WHERE REMOVE_TAG = CCREC.REMOVE_TAG
AND VIP_CARD_END_DATE = CCREC.VIP_CARD_END_DATE;

UPDATE TF_R_CARD_VIP
SET CARD_STATE_CODE = '1',
SERIAL_NUMBER = '',
end_date = to_date('2050-12-31 23:59:59',
'yyyy-mm-dd hh24:mi:ss')
WHERE RES_NO = CCREC.SERIAL_NUMBER;
COMMIT;
END LOOP;
CLOSE CC;

end P_CRM_UPDATE_VIP_CARD_STATE;
这是我写的存储过程 ,哪位大侠给看看吧,怎么能提高一下效率呢?

liuyinhuan0409
liuyinhuan0409 有没有楼主想要的答案咧
大约 7 年之前 回复

3个回答

我大概看了一下你的procedure,无非是做了两件事:
1.根据TF_F_CUST_VIP中的某些数据去update TF_R_CARD_VIP中的数据(这个可以用Merge语法)
2.update TF_F_CUST_VIP本table中的某些数据(这个就直接update)
其实这些动作没必要用游标去循环了,用游标全表循环自然效率低,可以参考下面修改的:

[code="sql"]
create or replace procedure P_CRM_UPDATE_VIP_CARD_STATE AS
BEGIN

Merge into TF_R_CARD_VIP t
using (SELECT A.SERIAL_NUMBER, A.REMOVE_TAG, A.VIP_CARD_END_DATE
FROM TF_F_CUST_VIP A
WHERE A.REMOVE_TAG = '0'
AND A.VIP_CARD_END_DATE < SYSDATE) aa
on (aa.SERIAL_NUMBER = t.RES_NO)
When matched then
update
SET CARD_STATE_CODE = '1',
SERIAL_NUMBER = '',
end_date = to_date('2050-12-31 23:59:59',
'yyyy-mm-dd hh24:mi:ss');

UPDATE TF_F_CUST_VIP
SET VIP_CARD_STATE = '4'
WHERE A.REMOVE_TAG = '0'
AND A.VIP_CARD_END_DATE < SYSDATE;

COMMIT;

end P_CRM_UPDATE_VIP_CARD_STATE;
[/code]

手写,未测试..

liuyinhuan0409
liuyinhuan0409 呵呵,希望能帮到你就好,大家共同学习~~
大约 7 年之前 回复
maomimi2213
maomimi2213 恩,数据库不好,都不知道什么时候该用什么,谢谢你 ,呵呵
大约 7 年之前 回复
liuyinhuan0409
liuyinhuan0409 看你的游标用的很熟练了,只是这个地方个人感觉没必要用游标了啦,仅供参考
大约 7 年之前 回复
maomimi2213
maomimi2213 其实我不知道该用什么去写,刚好会游标,就用了, 呵呵
大约 7 年之前 回复

不知道update表的数据量有多少,给个思路
1.看where条件执行要多久,如果数据量大,where条件没有索引,会很慢的。
2.看set字段是否建立了索引,如果有索引,update也会更新索引。

maomimi2213
maomimi2213 上万的数据,比较大
大约 7 年之前 回复

估计是数量较大吧

1.如果有索引的话,先drop掉,再build。

2.如果有制约的话,先disable,再enable

3.不用循环,用一句SQL处理。比如第一个处理
[code="sql"]
UPDATE TF_F_CUST_VIP B
SET VIP_CARD_STATE = '4'
WHERE EXISTS
(SELECT *
FROM TF_F_CUST_VIP A
WHERE A.REMOVE_TAG = '0'
AND A.VIP_CARD_END_DATE < SYSDATE
AND b.REMOVE_TAG =a.REMOVE_TAG
AND b.VIP_CARD_END_DATE =a.VIP_CARD_END_DATE
)
[/code]

未测试!

j_clxy
clxy大叔 有区别。 你的是查询出来,一条条循环做。 我的是一句SQL文处理掉。 区别就是不用再在存储过程里循环了。 特别这句 [code="sql"] UPDATE TF_F_CUST_VIP SET VIP_CARD_STATE = '4' WHERE REMOVE_TAG = CCREC.REMOVE_TAG AND VIP_CARD_END_DATE = CCREC.VIP_CARD_END_DATE; [/code] 我的猜测,这个where条件不足以限定只有1条数据吧?! 假如满足where条件的数据是复数的,那么你对同一条数据重复循环做update!
大约 7 年之前 回复
maomimi2213
maomimi2213 数据量是相当大,上午执行了好久也没执行完,你这样 写跟我那样写有什么区别吗?
大约 7 年之前 回复
j_clxy
clxy大叔 刚看到Dead_knight的回复,发现自己没说清楚。 正如他说的那样,上面的1,2也是指set字段,不是where字段。 比如索引,先drop掉,update,再build。
大约 7 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!