手把手教你大型表格的更新、删除和优化

是否能学习分区表的方式,从逻辑上对单表进行分区,从而加快删除的速度?说到此处,我们先来回顾下单表的物理存储结构:段–区–块。区是段的最小分配单元,一个区又包含多个块,那么能否利用区或块的物理特性来模拟分区呢?笔者尝试使用区来做分区,为什么不用块呢?因为一个数据库块能存储的数据量不超过1000行,故被排除。

我们利用ROWID对每一行进行按区分片,此处引入了Oracle内部函数dbms_rowid.rowid_create帮助我们按区进行ROWID分片,代码如下:

SQL> select A.FILE_ID,

A.EXTENT_ID,

A.BLOCK_ID,

A.BLOCKS,

' rowid between ' || '''' ||

dbms_rowid.rowid_create(1,

b.data_object_id,

a.relative_fno,

a.block_id,

0) || '''' || ' and ' || '''' ||

dbms_rowid.rowid_create(1,

b.data_object_id,

a.relative_fno,

a.block_id + blocks - 1,

999) || ''';'

from dba_extents a, dba_objects b

where a.segment_name = b.object_name

and a.owner = b.owner

and b.object_name = 'JASON'

and b.owner = 'SCOTT'

order by a.relative_fno, a.block_id;

按区分片后的信息输出如下图所示。

图 按区分片后的信息输出

有了以上的分片信息,我们只需要带入需要筛选的条件,使用匿名块批量删除即可,具体实现方式如下:

SQL> declare

cursor cur_rowid is

select dbms_rowid.rowid_create(1,

b.data_object_id,

a.relative_fno,

a.block_id,

0) begin_rowid,

dbms_rowid.rowid_create(1,

b.data_object_id,

a.relative_fno,

a.block_id + blocks - 1,

999) end_rowid

from dba_extents a, dba_objects b

where a.segment_name = b.object_name

and a.owner = b.owner

and b.object_name = 'JASON'

and b.owner = 'SCOTT'

order by a.relative_fno, a.block_id;

r_sql varchar2(4000);

begin

FOR cur in cur_rowid LOOP

r_sql := 'delete SCOTT.jason where OBJECT_TYPE=' || '''' || 'INDEX' || '''' ||

' and rowid between :1 and :2';

EXECUTE IMMEDIATE r_sql

using cur.begin_rowid, cur.end_rowid;

COMMIT;

END LOOP;

end;

在具体的实现过程中,大家只需要替换对应的SQL语句及用户名对象即可。

虽然按区构造ROWID分片进行删除,效率上比单纯的delete提高了好几倍,但整个执行过程并不是并行的,需要在不同的窗口进行人工操作,实现过程较为烦琐。那么还有没有更高效的方式呢?

Oracle从11g R2版本开始推出了DBMS_PARALLEL_EXECUTE包,能够高效地对大表进行DML操作。可以自定义并行度这一特点,使得DBMS_PARALLEL_EXECUTE包成为了最优的选择。实现代码如下:

 SQL> SET SERVEROUTPUT ON

SQL> BEGIN

DBMS_PARALLEL_EXECUTE.DROP_TASK ('test_task');

EXCEPTION WHEN OTHERS THEN

NULL;

END;

/



SQL> DECLARE

l_task VARCHAR2(30) := 'test_task';

l_sql_stmt VARCHAR2(32767);

l_try NUMBER;

l_status NUMBER;

BEGIN

-- Create the TASK

DBMS_PARALLEL_EXECUTE.CREATE_TASK (task_name => l_task);

-- Chunk the table by the ROWID

DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_ROWID

(

TASK_NAME => l_task,

TABLE_OWNER => 'JOE', <<<用户名

TABLE_NAME => 'OB2', <<<表名

BY_ROW => TRUE, <<<值为TRUE,表示chunk_size为行数,否则表示块数

CHUNK_SIZE => 2500 <<<自定义chunk的大小,这里表示2500行为一个chunk

);

-- DML to be execute in parallel

l_sql_stmt := 'delete OB2 where object_type = ''SYNONYM'' and rowid BETWEEN

:start_id AND :end_id'; <<<想要执行的SQL语句

-- Run the task

DBMS_PARALLEL_EXECUTE.RUN_TASK

(

TASK_NAME => l_task,

SQL_STMT => l_sql_stmt,

LANGUAGE_FLAG => DBMS_SQL.NATIVE,

PARALLEL_LEVEL => 2 <<<自定义执行并行度

);

-- If there is error, RESUME it for at most 2 times.

l_try := 0;

l_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS(l_task);

WHILE(l_try < 2 and l_status != DBMS_PARALLEL_EXECUTE.FINISHED)

LOOP

l_try := l_try + 1;

DBMS_PARALLEL_EXECUTE.RESUME_TASK(l_task);

l_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS(l_task);

END LOOP;

-- Done with processing; drop the task

DBMS_PARALLEL_EXECUTE.DROP_TASK(l_task);

EXCEPTION WHEN OTHERS THEN

DBMS_OUTPUT.PUT_LINE('Error in the code :' || SQLERRM);

END;

/

如上述脚本所示,DBMS_PARALLEL_EXECUTE包的使用方法较为简单,只需要修改标红的备注部分即可执行。以上这个脚本是通过ROWID进行切割的,当然切割表的方法还有另外两种,一是通过指定字段CREATE_CHUNKS_BY_NUMBER_COL来切割,二是通过自己指定SQL语句CREATE_CHUNKS_BY_SQL来切割,这里就不详细说明了,大家如想进一步了解,可自行搜索相关资料。

DBMS_PARALLEL_EXECUTE的基本原理是将一个大表以指定的块大小(chunk size)进行分片(chunk size 可以指定行数或块数),然后对多个分片进行并行删除(delete)或其他DML操作,每一个分片完成后立即提交,最后通过调用job进行并发控制操作。

所以,如果想要调用DBMS_PARALLEL_EXECUTE包,除了拥有此包的访问权限之外,还必须要有创建job的权限。

DBMS_PARALLEL_EXECUTE包的基本执行流程具体如下。

1)调用create_task(),创建任务(task)。

2)调用create_chunk_by_rowid(),创建分块规则。

3)编写自己需要执行的DML操作语句。

4)调用run_task(),运行任务。

5)调用drop_task(),即任务执行完成后,删除任务。

DBMS_PARALLEL_EXECUTE包涉及的相关视图如下:

DBA_PARALLEL_EXECUTE_TASKS
DBA_PARALLEL_EXECUTE_CHUNKS
dba_scheduler_jobs

在任务的执行过程中,可以通过上述视图实时监控任务的执行情况。

本文摘编于《DBA攻坚指南:左手Oracle,右手MySQL》,经出版方授权发布。(ISBN:9787111684336)转载请保留文章出处。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/259387.html<

(0)
管理的头像管理
上一篇2025-05-02 16:23
下一篇 2025-05-02 16:24

相关推荐

  • jsp空间购买和交换数据空间怎么买,有哪些注意事项?

    购买JSP空间时,是否考虑过数据交换空间的性能?简米科技(2003年始创,23年行业沉淀)与酷番云(工信部一类增值电信全牌照)这类持牌自营机房的服务商,能确保数据交换的高效稳定,是值得优先选择的合作伙伴,为什么JSP空间需要搭配独立的数据交换空间从JSP应用特性看数据交换需求JSP基于Java技术,常用于企业级……

    2026-08-11
    0
  • 建网站用香港空间效果怎么样,香港空间稳定吗?

    建网站用香港空间,对于创建网站资产来说,核心价值在于免备案和全球带宽优势,尤其适合外贸、跨境电商和需要快速启动的项目,但你必须权衡国内访问延迟,并选择有资质的服务商以保证资产安全,香港空间的核心优势与适用边界免备案:节省时间就是节省成本国内服务器需要备案,通常需要10到20天,香港空间无需备案,域名解析后即可上……

    2026-08-11
    0
  • Java连接云数据库的方法是什么,如何操作

    Java连接云数据库的核心在于通过JDBC驱动,结合云服务商提供的连接地址、端口、数据库名及认证信息,配置安全策略(如SSL、IP白名单),即可实现稳定高效的远程数据库访问,基础准备:JDBC驱动与依赖管理连接云数据库前,需要确保开发环境具备对应的JDBC驱动,以最常见的MySQL为例,你需要引入mysql-c……

    2026-08-11
    0
  • 建网站公安联网备案必须使用数据码吗,备案流程是什么

    网站备案包括ICP备案和公安联网备案,两者缺一不可,公安联网备案必须使用服务商提供的数据码,选择持有合法资质的服务商是顺利通过备案的前提,为什么网站必须进行公安联网备案根据公安部《计算机信息网络国际联网安全保护管理办法》,网站开通后30日内必须到公安机关办理备案手续,未完成公安备案的网站,面临责令整改、关闭网站……

    2026-08-10
    0
  • 建一个企业网站大概需要多少钱?,怎么收费?

    建网站要多少钱,没有一个固定的数字,几百到几万都可能,但真正的“创建网站资产”绝不仅仅是初次投入的成本,而是基于长期稳定、合规和安全的持续性投入,其中核心取决于你选择了什么样的“地基”来承载你的业务,建站预算的构成与行业基准当你开始规划一个网站,最先面对的就是预算问题,一个常见的误区是只关注网站“看起来”的建造……

    2026-08-10
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注