- 浏览: 51900 次
- 性别:
- 来自: 北京
最新评论
能不能想办法 提升一下如下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 971Oracle的left join中on和where的区别 数 ... -
动态sql拼接单引号与 变量赋值
2012-06-21 10:09 3844if (lower(s_table)='gl_deta ... -
ora-00031:session marked for kill处理oracle中杀不掉的锁
2012-06-19 16:36 1058转: 一些ORACLE中的进程被杀掉后,状态被置为" ... -
使用DBLINK为远程数据库的用户表创建同义词
2012-06-19 14:39 9221、创建db_link create database l ... -
以字符串数组为输入参数的存储过程
2012-06-19 14:27 2738今天项目中需要用到存 ... -
函数的使用
2012-06-04 17:09 978create or replace function Fun_ ... -
Oracle中decode的使简单例子
2012-06-04 17:06 1474decode(字段,表达式1,表达式2,表达式。。。) 当,字 ... -
oracle触发器
2012-04-20 09:11 738表: A 字段:a, b, c 当修改a字段的值时触发 c字段 ... -
oracle的全文索引
2012-04-16 14:29 789已有几个项目组开始使 ... -
单独的plsql链接数据库
2011-10-14 16:03 901转的: plsql 可不可以 ... -
Oracle经验集锦
2011-09-24 13:32 6851.删除表空间 DROP ... -
两个数据库字符集不一样,如何快速增量同步数据.
2011-09-23 15:00 1145环境: DB-A 字符集:US7ASC ... -
Oracle分区表详解 .
2011-08-06 10:42 641一、Oracle分区简介 ORACLE的分区是一种处理超大型 ... -
oracle全文索引的简单配置
2011-08-04 23:49 10001.创建数据存储定义(Datastore),使用多列数据存储在 ... -
用java调用oracle存储过程总结
2011-08-04 23:45 6401、什么是存储过程。存 ... -
Oracle SCN详解
2011-08-04 23:38 602pre. Oracle中的SCN(system change ... -
oracle 数据库里查看表空间使用状况
2011-08-04 23:34 642oracle表空间的事情状况要经常查看,一般空闲比例过低的时候 ... -
采用全文索引解决模糊查询速度慢的问题
2011-08-04 23:31 756众所周知,使用 like 进行模糊查询速度极差,包括 like ... -
oracle9i在windows上的dataguard配置
2011-08-04 23:23 704主库:win2003 server ora9i(9.2.0.1 ... -
Rman duplicate数据库复制(单系统)
2011-08-04 23:22 647一、实验环境: 1. 虚拟机:VMware Ser ...
相关推荐
### 利用ROWID快速在线更新海量数据的关键技术点 #### 一、ROWID与数据库性能优化 **ROWID** 是 Oracle 数据库中一个非常重要的概念,它是一种特殊类型的列,用于唯一标识表中的一行数据。ROWID 的格式通常包含...
在处理大型数据库,尤其是当数据...在实际应用中,根据具体情况选择合适的优化方案,能够显著提升数据库性能,改善用户体验。在面对大规模数据集时,更需要仔细评估各种优化手段的优劣,以保证数据库操作的高效和稳定。
- **INSERT**、**UPDATE** 和 **DELETE**:数据修改语言(DML)操作可以利用并行处理提高执行速度。 - **REBUILD INDEX**:重建索引过程可以并行化以提高效率。 - **PARALLEL SQL*LOADER**:数据导入过程中可以利用...
了解和利用Rowid对于提升数据库性能,优化SQL查询语句以及进行数据库管理都有极大的帮助。不过,因为Rowid是Oracle数据库特有的,如果在使用其他关系型数据库系统时,如MySQL或SQL Server,我们则无法找到类似的功能...
对于大型数据库系统来说,优化`UPDATE`语句能够显著提升数据处理速度和效率,减少资源消耗,提高整体性能。本文将通过分析提供的代码示例来探讨几种常见的`UPDATE`语句优化技巧。 #### 一、理解提供的SQL示例 首先...
然而,创建和维护索引也有代价,如增加存储需求、影响INSERT、DELETE、UPDATE操作的性能。因此,明智地选择和管理索引至关重要。 访问表的方式分为全表扫描和通过ROWID访问。全表扫描是对表中的每条记录进行顺序...
总结起来,提升GBase 8s ODBC应用程序性能的关键在于合理利用定位更新和删除,以及通过SQLSpecialColumns找到最佳的列集进行数据操作。同时,注意避免过于复杂的查询,尽可能利用数据库的内部机制,如唯一索引和伪列...
综上所述,通过对Oracle数据库中PL/SQL性能优化技术的研究,我们发现合理利用ROWID、确保数据类型一致以及优化IF条件的顺序等方法可以在很大程度上提升系统的整体性能。这些技术的应用不仅能够提高单个查询的速度,...
2. **ROWID访问**:利用ROWID这一特殊的标识符,可以直接定位到特定的记录位置。ROWID包含着记录在物理存储中的位置信息,通过索引来实现数据与其物理位置之间的关联,从而提高访问效率。 #### 四、SQL对表与索引的...
在本主题中,我们将深入探讨如何利用AJAX来控制HTML表格(table)的内容显示方式,特别是在点击单元格时实现内容的编辑功能。 ### AJAX基础 AJAX允许在不刷新整个页面的情况下与服务器进行异步数据交换。它通过...
对于经常使用的 PL/SQL 包,可以通过编写脚本来自动固定这些包在共享池中的位置,进一步提升性能。 #### 14. 使用和修改 DBMS_SHARED_POOL.SIZES DBMS_SHARED_POOL.SIZES 提供了控制共享池中不同对象大小的能力,...
5. **ROWID利用**:对单行记录的`DELETE`、`UPDATE`操作,使用`ROWID`可以提升速度。 6. **优化线索**:通过优化线索控制访问路径。 7. **显式游标**:使用显式游标优于隐式游标,便于控制和调试。 以上规范和建议...
### SQL性能优化详解 #### 一、SQL性能优化的基本原则 在进行SQL性能优化之前,首先需要理解几个基本原则: ...通过遵循以上原则和步骤,可以显著提升SQL语句的执行效率,进而提高整个系统的性能。
另外,使用ROWID进行更新操作可能会导致性能更差,因为它增加了额外的寻址步骤,且可能会引入不确定性。 在编写SQL语句时,还需要注意其他优化策略,比如使用索引、避免全表扫描、减少子查询的使用,以及合理利用...
SQL优化是数据库管理中至关重要的一个环节,它可以显著提升数据库的性能,降低资源消耗,从而提高系统的整体效率。以下是对标题和描述中提到的一些关键知识点的详细解释: 1. **选择有效的表名顺序**:在编写SQL...
理解数据库处理时间的基本准则,如I/O延迟、CPU利用率和网络延迟,有助于优化系统性能。 27. **入侵防护**: 了解常见的Oracle入侵手段,如SQL注入,加强权限控制和审计,以防范安全风险。 28. **数据库优化**: ...
在进行数据检索或维护时,直接使用`Rowid`能显著提升性能,特别是在大型数据库中。 2. **管理Oracle内存** Oracle内存管理主要包括SGA(共享全局区)和PGA(程序全局区)。其中,SGA是所有用户进程共享的内存区域...
在SQL Server数据库管理系统中,索引是提升查询性能的关键元素,尤其当面对大量数据时。本指南将深入探讨两种主要的索引类型:群集索引(Clustered Index)和非群集索引(Nonclustered Index),以及如何在设计过程...
熟悉基本的Unix命令,如ls(列出目录内容),cd(改变目录),mv(移动文件),cp(复制文件),mkdir(创建目录)和rm(删除文件)等,是有效利用Unix环境的关键。Unix还提供了强大的文本处理工具,如grep、sed和...