- 浏览: 49174 次
- 性别:
- 来自: 北京
最新评论
能不能想办法 提升一下如下update语句的性能
UPDATE OPT_ACCT_FDIM A
SET ACCT_SKID = (SELECT ACCT_SKID
FROM OPT_ACCT_FDIM_BKP B
WHERE A.ACCT_ID = B.ACCT_ID);
SELECT COUNT(*) FROM OPT_ACCT_FDIM; -------这个表 有 226474 条数据
SELECT COUNT(*) FROM OPT_ACCT_FDIM_BKP; ------ 这个表 有 227817 条数据
SELECT COUNT(*)
FROM OPT_ACCT_FDIM A, OPT_ACCT_FDIM_BKP B
WHERE A.ACCT_ID = B.ACCT_ID
AND A.ACCT_SKID <> B.ACCT_SKID; -------要更新 226474 条
那么现在已经很清楚了,业务逻辑就是根据 根据2个表的acct_id 字段关联,然后根据B表的字段update A表,那么这里呢 要更新整个A表
UPDATE的执行计划我们就不用看了,肯定是HASH JOIN,开发人员说 这个update 跑了30分钟,还没完成,其实我估计 这个SQL至少得1小时才能跑完。
其实,select 语句是很好优化的,但是update,delete这样的SQL, 如果要想从SQL上面优化,几乎不可能,优化update,delete我们要用PL/SQL来实现。
对于我们这里的UPDATE语句,我们可以利用rowid 来快速更新,PL/SQL 代码如下:
SQL> DECLARE
2 CURSOR CUR_B IS
3 SELECT
4 B.ACCT_ID, B.ACCT_SKID, A.ROWID ROW_ID
5 FROM OPT_ACCT_DIM A, OPT_ACCT_DIM_BKP B
6 WHERE A.ACCT_ID = B.ACCT_ID
7 ORDER BY A.ROWID; ---如果表的数据量不是很大,可以不用 order by rowid
8 V_COUNTER NUMBER;
9 BEGIN
10 V_COUNTER := 0;
11 FOR ROW_B IN CUR_B LOOP
12 UPDATE OPT_ACCT_DIM
13 SET ACCT_SKID = ROW_B.ACCT_SKID
14 WHERE ROWID = ROW_B.ROW_ID;
15 V_COUNTER := V_COUNTER + 1;
16 IF (V_COUNTER >= 1000) THEN
17 COMMIT;
18 V_COUNTER := 0;
19 END IF;
20 END LOOP;
21 COMMIT;
22 END;
23 /
PL/SQL procedure successfully completed.
Elapsed: 00:01:21.58
现在多快啊,1分22秒搞定
其实,以前的update就相当于下面的PL/SQL代码:
declare
cursor c_update is
select b.acct_skid, a.acct_id
from opt_acct_fdim a, opt_acct_fdim_bkp b
where a.acct_id = b.acct_id;
v_counter number;
begin
v_counter := 0;
for v_row in c_update loop
update opt_acct_fdim
set acct_skid = v_row.acct_skid
where acct_id = v_row.acct_id; ---注意,这里没有rowid
v_counter := v_counter + 1;
if (v_counter >= 1000) then
commit;
v_counter := 0;
end if;
end loop;
commit;
end;
/
我自己测试了一下上面的PL/SQL 代码,跑了30分钟没跑完,为什么跑这么久呢?
其实原因就在于这里:
update opt_acct_fdim
set acct_skid = v_row.acct_skid
where acct_id = v_row.acct_id;
因为缺少 rowid定位,那么又会对表进行全表扫描,而且每更新一行就会去做全表扫描。
而我们利用rowid定位block,那么不用 全表扫描了 性能提升上 百倍。
12 UPDATE OPT_ACCT_DIM
13 SET ACCT_SKID = ROW_B.ACCT_SKID
14 WHERE ROWID = ROW_B.ROW_ID;
其实这本书 Oracle Database 10g PL/SQL 程序设计 ---清华大学出版社 p132页 里面就有这个方法
itpub 这篇帖子:http://www.itpub.net/viewthread.php?tid=1052077 也提到过这个方法
总结:对于大批量的update,delete,我们可以利用rowid 来进行优化,性能往往提升 上百倍。
UPDATE OPT_ACCT_FDIM A
SET ACCT_SKID = (SELECT ACCT_SKID
FROM OPT_ACCT_FDIM_BKP B
WHERE A.ACCT_ID = B.ACCT_ID);
SELECT COUNT(*) FROM OPT_ACCT_FDIM; -------这个表 有 226474 条数据
SELECT COUNT(*) FROM OPT_ACCT_FDIM_BKP; ------ 这个表 有 227817 条数据
SELECT COUNT(*)
FROM OPT_ACCT_FDIM A, OPT_ACCT_FDIM_BKP B
WHERE A.ACCT_ID = B.ACCT_ID
AND A.ACCT_SKID <> B.ACCT_SKID; -------要更新 226474 条
那么现在已经很清楚了,业务逻辑就是根据 根据2个表的acct_id 字段关联,然后根据B表的字段update A表,那么这里呢 要更新整个A表
UPDATE的执行计划我们就不用看了,肯定是HASH JOIN,开发人员说 这个update 跑了30分钟,还没完成,其实我估计 这个SQL至少得1小时才能跑完。
其实,select 语句是很好优化的,但是update,delete这样的SQL, 如果要想从SQL上面优化,几乎不可能,优化update,delete我们要用PL/SQL来实现。
对于我们这里的UPDATE语句,我们可以利用rowid 来快速更新,PL/SQL 代码如下:
SQL> DECLARE
2 CURSOR CUR_B IS
3 SELECT
4 B.ACCT_ID, B.ACCT_SKID, A.ROWID ROW_ID
5 FROM OPT_ACCT_DIM A, OPT_ACCT_DIM_BKP B
6 WHERE A.ACCT_ID = B.ACCT_ID
7 ORDER BY A.ROWID; ---如果表的数据量不是很大,可以不用 order by rowid
8 V_COUNTER NUMBER;
9 BEGIN
10 V_COUNTER := 0;
11 FOR ROW_B IN CUR_B LOOP
12 UPDATE OPT_ACCT_DIM
13 SET ACCT_SKID = ROW_B.ACCT_SKID
14 WHERE ROWID = ROW_B.ROW_ID;
15 V_COUNTER := V_COUNTER + 1;
16 IF (V_COUNTER >= 1000) THEN
17 COMMIT;
18 V_COUNTER := 0;
19 END IF;
20 END LOOP;
21 COMMIT;
22 END;
23 /
PL/SQL procedure successfully completed.
Elapsed: 00:01:21.58
现在多快啊,1分22秒搞定
其实,以前的update就相当于下面的PL/SQL代码:
declare
cursor c_update is
select b.acct_skid, a.acct_id
from opt_acct_fdim a, opt_acct_fdim_bkp b
where a.acct_id = b.acct_id;
v_counter number;
begin
v_counter := 0;
for v_row in c_update loop
update opt_acct_fdim
set acct_skid = v_row.acct_skid
where acct_id = v_row.acct_id; ---注意,这里没有rowid
v_counter := v_counter + 1;
if (v_counter >= 1000) then
commit;
v_counter := 0;
end if;
end loop;
commit;
end;
/
我自己测试了一下上面的PL/SQL 代码,跑了30分钟没跑完,为什么跑这么久呢?
其实原因就在于这里:
update opt_acct_fdim
set acct_skid = v_row.acct_skid
where acct_id = v_row.acct_id;
因为缺少 rowid定位,那么又会对表进行全表扫描,而且每更新一行就会去做全表扫描。
而我们利用rowid定位block,那么不用 全表扫描了 性能提升上 百倍。
12 UPDATE OPT_ACCT_DIM
13 SET ACCT_SKID = ROW_B.ACCT_SKID
14 WHERE ROWID = ROW_B.ROW_ID;
其实这本书 Oracle Database 10g PL/SQL 程序设计 ---清华大学出版社 p132页 里面就有这个方法
itpub 这篇帖子:http://www.itpub.net/viewthread.php?tid=1052077 也提到过这个方法
总结:对于大批量的update,delete,我们可以利用rowid 来进行优化,性能往往提升 上百倍。
发表评论
-
Oracle的left join中on和where的区别
2012-10-26 15:43 874Oracle的left join中on和where的区别 数 ... -
动态sql拼接单引号与 变量赋值
2012-06-21 10:09 3719if (lower(s_table)='gl_deta ... -
ora-00031:session marked for kill处理oracle中杀不掉的锁
2012-06-19 16:36 956转: 一些ORACLE中的进程被杀掉后,状态被置为" ... -
使用DBLINK为远程数据库的用户表创建同义词
2012-06-19 14:39 8341、创建db_link create database l ... -
以字符串数组为输入参数的存储过程
2012-06-19 14:27 2650今天项目中需要用到存 ... -
函数的使用
2012-06-04 17:09 891create or replace function Fun_ ... -
Oracle中decode的使简单例子
2012-06-04 17:06 1385decode(字段,表达式1,表达式2,表达式。。。) 当,字 ... -
oracle触发器
2012-04-20 09:11 645表: A 字段:a, b, c 当修改a字段的值时触发 c字段 ... -
oracle的全文索引
2012-04-16 14:29 738已有几个项目组开始使 ... -
单独的plsql链接数据库
2011-10-14 16:03 854转的: plsql 可不可以 ... -
Oracle经验集锦
2011-09-24 13:32 6401.删除表空间 DROP ... -
两个数据库字符集不一样,如何快速增量同步数据.
2011-09-23 15:00 1093环境: DB-A 字符集:US7ASC ... -
Oracle分区表详解 .
2011-08-06 10:42 593一、Oracle分区简介 ORACLE的分区是一种处理超大型 ... -
oracle全文索引的简单配置
2011-08-04 23:49 9501.创建数据存储定义(Datastore),使用多列数据存储在 ... -
用java调用oracle存储过程总结
2011-08-04 23:45 5901、什么是存储过程。存 ... -
Oracle SCN详解
2011-08-04 23:38 560pre. Oracle中的SCN(system change ... -
oracle 数据库里查看表空间使用状况
2011-08-04 23:34 595oracle表空间的事情状况要经常查看,一般空闲比例过低的时候 ... -
采用全文索引解决模糊查询速度慢的问题
2011-08-04 23:31 709众所周知,使用 like 进行模糊查询速度极差,包括 like ... -
oracle9i在windows上的dataguard配置
2011-08-04 23:23 655主库:win2003 server ora9i(9.2.0.1 ... -
Rman duplicate数据库复制(单系统)
2011-08-04 23:22 594一、实验环境: 1. 虚拟机:VMware Ser ...
相关推荐
sql学习 利用rowid提升sql性能的常见优化案例.sql
oracle_SQL中 rowid 和rownum的使用
Oracle数据库rowid深入探析.pdf
利用rowid快速在线更新海量数据 利用rowid快速在线更新海量数据
sql学习 11g中的rowid的访问优化提升分析比较.sql
sql学习 执行计划SQL写法差异改变之5_rowid 的影响.sql
mysql虚拟了一个rowid(类似跟oracle的rowid)--SQL语句
对一个大表进行UPDATE,DELETE,如果在一个SESSION里面运行SQL,很容易引发undo不够, 或者由于一些原因,导致回滚,这个是灾难
rowid与rownumber的介绍 rowid rownumber
sql学习 oracle 行定位与rowid描述.sql
sql学习 08.TABLE ACCESS BY INDEX ROWID.sql
sql学习 03.TABLE ACCESS BY USER ROWID.sql
s = select a.*,a.rowid from u1 = ucr_crm1. u2 = ucr_crm2. u3 = ucr_crm3. u4 = ucr_crm4. u5 = ucr_crm4. u11 = ucr_cen1. ins = insert into s1 =select a.*,a.rowid from ucr_crm1. s2 = select a.*,...
sql学习 分区表其他知识1_rowid.sql
1. 选用适合的ORACLE优化器 2. 访问Table的方式 a.全表扫描 ...通过ROWID访问表 3. 共享SQL语句 4. 选择最有效率的表名顺序(只在基于规则的优化器中有效) 5. WHERE子句中的连接顺序 。。。。。等等
贺辞 序 前言 第1章 建立和配置数据库 ...9.1.4 利用 DBMS_STATS 收集性能统计 数据 9.2 新索引类型 9.2.1 基于函数的索引 9.2.2 反向键索引 9.2.3 降序索引 9.2.4 索引编排表 9.2.5 管理索引的...
目录 序 ............................................................................................... 17 前言 ...........................................................................................
oracle rowid rownum 等组成原理
21天学习SQL V1.0.pdf 66 SQL 21 日自学通(V1.0) 翻译人笨猪 ...日期/时间函数............................................................................................................ADD_MONTHS..................
5.5.1 ROWID ............................................ 244 5.5.2 UID 和 USER ........................................ 244 5.5.3 TRXID ............................................ 244 ...