设为首页 加入收藏

TOP

删除大表的数据:普通删除语句和游标处理的比较(一)
2015-07-24 12:05:16 来源: 作者: 【 】 浏览:91
Tags:删除 数据 普通 语句 游标 处理 比较

一、前言

WHERE条件用不到索引的情况下如何删除大表记录?文章中只是列举出其中一种方式而已,但仍然存在很多不严谨的地方.只是

轻描淡写随着数据表越来越大,历史数据的处理将越来越困难.且过滤字段没有索引(如时间)字段,而创建索引是需要临时表空间排序的.有越来越大,创建的维护工作也随之越来越难.

除了本文介绍的方法以外,还可以通过以下几种方法来维护历史数据:

1. 创建历史表,将历史数据定期移至历史表,让源表保持"瘦小身材"(源表会有碎片,需要定期对表和索引进行重建)

2. ORACLE系统包DBMS_REDEFINITION实现表的在线重定义

3. 把源表做分区处理,历史数据的维护可以转化成表/索引分区的维护.

?

本文将对以下几种方法做比较:

1. 普通删除语句(delete from tabname where condition1...condition2...)

2. 通过存储过程(每次提取一条)

3. 通过存储过程(批量提取)

?

以一张近500M的表作为实验对象,该表没有任何索引.总条数400多万:

SQL> select bytes/1024/1024 from user_segments where segment_name='ROBO';

BYTES/1024/1024
---------------
472 ---

SQL> select count(*) from robo;

COUNT(*)
----------
4154240 ----约400万条数据

SQL> select count(*) from robo where owner='TEST';

COUNT(*)
----------
4992 ---近5000条数据

SQL> select count(*) from robo where owner='SYS';

COUNT(*)
----------
1909760 ---近200万条数据

二、实验过程

1)假设待删除数据量小:

1. 普通删除的方法:

SQL> delete from robo where owner='TEST';
delete from robo
where
owner='TEST'

性能数据:

-------------

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 1 1 0 0
Execute 1 0.65 0.64 59842 60092 5280 4992
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.65 0.64 59843 60093 5280 4992

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 52

Rows Row Source Operation
------- ---------------------------------------------------
0 DELETE ROBO (cr=60092 pr=59842 pw=0 time=642682 us)
4992 TABLE ACCESS FULL ROBO (cr=60092 pr=59840 pw=0 time=485683 us)

只要全表扫描一次,删除效率很快

?

2. 游标处理(每次提取一条)

declare
v_rowid varchar2(25);
v_sqltext varchar2(200);
cursor c1 is select rowid from robo where owner='TEST';
begin
v_sqltext := 'delete from robo where rowid=:1';
open c1;
loop
fetch c1 into v_rowid;
execute immediate v_sqltext using v_rowid;
exit when c1%notfound;
end loop;
dbms_output.put_line(c1%rowcount||' row deleted.');
close c1;
end;
/

4992 row deleted.

PL/SQL procedure successfully completed.

?

性能数据:

-------------

delete from robo
where
rowid=:1


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 4993 0.33 0.31 1 4993 5280 4992
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4994 0.33 0.31 1 4993 5280 4992

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 52 (recursive depth: 1)

Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
db file sequential read 1 0.00 0.00
********************************************************************************

declare
v_rowid varchar2(25);
v_sqltext varchar2(200);
cursor c1 is select rowid from robo where owner='TEST';
begin
v_sqltext := 'delete from robo where rowid=:1';
open c1;
loop
fetch c1 into v_rowid;
execute immediate v_sqltext using v_rowid;
exit when c1%notfound;
end loop;
dbms_output.put_line(c1%rowcount||' row deleted.');
close c1;
end;

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.26 0.22 0 0 0 1
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ----

首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇数据库中nextVal,currVal的应用. 下一篇OGGrep运行慢的分析步骤

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: