科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道关于Oracle数据库中行迁移/行链接的问题

关于Oracle数据库中行迁移/行链接的问题

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

一、行迁移/行链接的介绍 在实际的工作中我们经常会碰到一些Oracle数据库性能较低的问题,当然,引起Oracle数据库性能较低的原因是多方面的。

作者:中国IT实验室 来源:中国IT实验室 2007年10月11日

关键字: ORACLE

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共4页)

        方法四:使用EXP/IMP工具清除行迁移的方法

        1. 使用EXP导出存在有行迁移的表。

        2. 然后TRUNCATE原来的表。

        3. IMP开始导出的表。

        4. 重建表上所有的索引。(可选)

        使用这种方法可以不用重建索引,省去了这部分时间,但是完成之后索引的使用效率不会很高,最好是在以后逐步的在线重建索引,这样是可以不需要中断业务的。但是需要考虑的是IMP的时候会比较慢,而且会占用比较大的IO,应该选择在应用不是很繁忙的时候做这项工作,否则会对应用的正常运行产生较大的影响。对于这种方法还存在有一个比较大的弊端,就是在EXP表的时候要保证该表是没有数据的更新或者是只读状态的,不能对表有插入或者更新操作,否则会导致数据的丢失。

        SQL> select count(*) from test;

        COUNT(*)

        ----------

        169344

        SQL> truncate table chained_rows;

        Table truncated.

        SQL> analyze table test LIST CHAINED ROWS INTO chained_rows;

        Table analyzed.

        SQL> select count(*) from chained_rows;

        COUNT(*)

        ----------

        3294

        $ exp allan/allan file=test.dmp tables=test

        Export: Release 9.2.0.3.0 - Production on Sun Jun 6 13:50:08 2004

        Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

        Connected to: Oracle9i Enterprise Edition Release 9.2.0.3.0 - Production

        With the Partitioning, OLAP and Oracle Data Mining options

        JServer Release 9.2.0.3.0 - Production

        Export done in ZHS16GBK character set and AL16UTF16 NCHAR character set

        About to export specified tables via Conventional Path ...

        . . exporting table TEST 169344 rows exported

        Export terminated successfully without warnings.

        $ sqlplus allan/allan

        SQL*Plus: Release 9.2.0.3.0 - Production on Sun Jun 6 13:50:43 2004

        Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved

        Connected to:

        Oracle9i Enterprise Edition Release 9.2.0.3.0 - Production

        With the Partitioning, OLAP and Oracle Data Mining options

        JServer Release 9.2.0.3.0 - Production

        SQL> truncate table test;

        Table truncated.

        SQL> exit

        Disconnected from Oracle9i Enterprise Edition Release 9.2.0.3.0 - Production

        With the Partitioning, OLAP and Oracle Data Mining options

        JServer Release 9.2.0.3.0 - Production

        $ imp allan/allan file=test.dmp full=y ignore=y buffer=5000000

        Import: Release 9.2.0.3.0 - Production on Sun Jun 6 13:51:24 2004

        Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

        Connected to: Oracle9i Enterprise Edition Release 9.2.0.3.0 - Production

        With the Partitioning, OLAP and Oracle Data Mining options

        JServer Release 9.2.0.3.0 - Production

        Export file created by EXPORT:V09.02.00 via conventional path

        import done in ZHS16GBK character set and AL16UTF16 NCHAR character set

        . importing ALLAN's objects into ALLAN

        . . importing table "TEST" 169344 rows imported

        Import terminated successfully without warnings.

        $ sqlplus allan/allan

        SQL*Plus: Release 9.2.0.3.0 - Production on Sun Jun 6 13:52:53 2004

        Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

        Connected to:

        Oracle9i Enterprise Edition Release 9.2.0.3.0 - Production

        With the Partitioning, OLAP and Oracle Data Mining options

        JServer Release 9.2.0.3.0 - Production

        SQL> select count(*) from test;

        COUNT(*)

        ----------

        169344

        SQL> select index_name from user_indexes where table_name='TEST';

        INDEX_NAME

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

        OBJ_INDEX

        SQL> alter index OBJ_INDEX rebuild online;

        Index altered.

        SQL> truncate table chained_rows;

        Table truncated.

        SQL> analyze table test LIST CHAINED ROWS INTO chained_rows;

        Table analyzed.

        SQL> select count(*) from chained_rows;

        COUNT(*)

        ----------

        0

        方法五:使用MOVE命令来清除行迁移的方法

        1. 查看要清除行迁移的表所在的表空间。

        Select table_name,tablespace_name from user_tables where table_name='table_name’;

        2. 查看要清除行迁移的表上的具体索引。

        select index_name,table_name from user_indexes where table_name=‘table_name’;

        3. Move要清除RM的表到指定的表空间中去。

        alter table table_name move tablespace tablespace_name;

        4. 重建表上的所有索引。

        alter index index_name rebuild;

        这种方法适用于8i及其以上的数据库版本,主要是利用数据库的一个MOVE命令来实现行迁移的清除的,MOVE命令的实质其实就是INSERT … SELECT的一个过程,在MOVE表的过程中是需要两倍的原来的表大小的,因为中间过程是要保留原来的旧表的,新表创建完成后旧表就被删除并释放空间了。MOVE的时候要注意后面一定要加上表空间参数,所以必须要先知道表所在的表空间;因为MOVE表之后需要重建索引,所以之前要确定表上的所有的索引。

        这种方法对于表记录数很大或者表上索引太多的情况不太适用,因为本身的MOVE就会很慢, 而且MOVE表的时候会要锁定表,时间长了会导致对表的其他操作出现问题,导致数据插入不了丢失数据;MOVE表后还要重建索引,索引太多了的话重建的时间也会太长;再者,这个方法也比较消耗资源,因此强烈建议在业务不繁忙的时候再执行。

        以下是一个具体在生产数据库上清除行迁移的例子,在这之前已经调整过表的pctfree参数至一个合适的值了:

        SQL>ANALYZE TABLE SERVICE LIST CHAINED ROWS INTO chained_rows;

        Table analyzed.

        SQL>SELECT count(*) from chained_rows;

        COUNT(*)

        ----------

        9145

        SQL>select table_name,tablespace_name from user_tables where table_name='SERVICE';

        TABLE_NAME TABLESPACE_NAME

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

        SERVICE DATA

        SQL>select index_name,table_name from user_indexes where table_name='SERVICE';

        INDEX_NAME TABLE_NAME

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

        I_SERVICE_ACCOUNTNUM SERVICE

        I_SERVICE_DATEACTIVATED SERVICE

        I_SERVICE_SC_S SERVICE

        I_SERVICE_SERVICECODE SERVICE

        PK_SERVICE_SID SERVICE

        SQL>select count(*) from SERVICE;

        COUNT(*)

        ----------

        518718

        SQL>alter table SERVICE move tablespace DATA;

        Table altered.

        SQL>alter index I_SERVICE_ACCOUNTNUM rebuild;

        Index altered.

        SQL>alter index I_SERVICE_DATEACTIVATED rebuild;

        Index altered.

        SQL>alter index I_SERVICE_SC_S rebuild;

        Index altered.

        SQL>alter index I_SERVICE_SERVICECODE rebuild;

        Index altered.

        SQL>alter index PK_SERVICE_SID rebuild;

        Index altered.

        SQL>truncate table chained_rows;

        Table truncated.

        SQL>ANALYZE TABLE SERVICE LIST CHAINED ROWS INTO chained_rows;

        Table analyzed.

        SQL>SELECT count(*) from chained_rows;

        COUNT(*)

        ----------

        0

        利用MOVE命令来清除行迁移,执行的命令都相对比较的简单,上面的例子中清除表SERVCIE中的行迁移的时间大概在五分钟左右,其中move命令执行的时间为不到两分钟,也就是锁表的时间大概是不到两分钟,对于大多数的应用来说一般问题都是不大的,放在系统闲的时候执行基本上不会对应用产生什么太多的影响。

        方法六:对于一些行迁移数量巨大而且表记录数巨大的表的行迁移的清除方法

        1. 使用TOAD工具或者别的方法获取存在有大量行迁移并且表记录很大的表的重建表的SQL,然后保存为脚本。

        2. 使用RENAME命令将原始表重命名为一个备份表,然后删除别的表对原始表上的限制、以及原始表上的外键和索引。

        3. 利用1中生成的脚本重建原始表,以及表上的限制,外键,索引等对象。

        4. 然后按表模式导出2中备份的表,然后导入到另外的一个临时中转的数据库库中,因为表的名字已经改变,所以导入后需要RENAME表为原来的名字,然后重新导出,最后再导入到原来的数据库中。

        这种方法主要是用来针对一些数据量比较大,并且表上的行迁移也比较多的表的行迁移清除。对于这些大表的行迁移的清除,正常来说都需要停应用一段较长时间才能够清除掉,让人感觉比较的头疼,对于7*24小时的应用来说,down机的时间越长损失则越大,当然是要尽量的减短down机的时间。但是因为表本身比较大,不管怎样做什么操作都是会比较耗费时间和资源的,但是如果应用在某段时间内主要是以插入数据为主,更新数据和删除数据都很少的,因此可以考虑可以采用这么一种方法:先重命名表,然后重新建立一个和原来一样的表,用来保证之后的应用的数据是可以正常插入的,从而使应用不用停很久,因为重建一个没有任何数据的表结构的过程是很短暂的,大概需要几秒钟的时间,而重建好表了后就能保证应用能够正常的写入数据,从而使应用几乎不用停顿,然后把开始重命名的原始表按表模式导出,因为表的名字已经被改变,因此需要一个临时库来导入这些数据,然后重命名回原来的名字,然后按原来的表名导出后再重新导入原始数据库,这样操作起来虽然会比较麻烦,但是却是一种很有效很实际的方法,速度也很快,导出后导入,因为本身表结构已经建立好了,不需要其他任何的多的操作,而且最关键的是这种方法所需要的down机时间是最短的。

        SQL>ALTER TABLE USER.PAY RENAME TO PAY_X ;

        然后导出PAY_X表;

        $ exp USER/USER file=PAY_X.dmp tables=PAY_X

        SQL>ALTER TABLE USER.BATCHPAYMENTDETAIL DROP CONSTRAINT FK_BATCHPAYMENTDETAIL_OPAYID ;

        SQL>ALTER TABLE USER.DEPOSITCLASSIFY DROP CONSTRAINT FK_DEPOSITCLASSIFY2 ;

        SQL>ALTER TABLE USER.DEPOSITCREDITLOG DROP CONSTRAINT FK_DEPOSITCREDITLOG2 ;

        SQL>ALTER TABLE USER.DEPOSIT DROP CONSTRAINT SYS_C003423 ;

        SQL>ALTER TABLE USER.PAY_X DROP CONSTRAINT SYS_C003549 ;

        SQL>DROP INDEX USER.I_PAY_STAFFID ;

        SQL>CREATE TABLE USER.PAY

        (

        PAYID NUMBER(9),

        ACCOUNTNUM NUMBER(9),

        TOTAL NUMBER(12,2),

        PREVPAY NUMBER(12,2),

        PAY NUMBER(12,2),

        STAFFID NUMBER(9),

        PROCESSDATE DATE,

        PAYNO CHAR(12),

        TYPE CHAR(2) DEFAULT '0',

        PAYMENTMETHOD CHAR(1) DEFAULT '0',

        PAYMENTMETHODID VARCHAR2(20),

        BANKACCOUNT VARCHAR2(32),

        PAYMENTID NUMBER(9),

        STATUS CHAR(1) DEFAULT '0',

        MEMO VARCHAR2(255),

        SERVICEID NUMBER(9),

        CURRENTDEPOSITID NUMBER(9),

        SHOULDPROCESSDATE DATE DEFAULT sysdate,

        ORIGINALEXPIREDATE DATE,

        ORIGINALCANCELDATE DATE,

        EXPIREDATE DATE,

        CANCELDATE DATE,

        DEPOSITTYPE CHAR(1)

        )

        TABLESPACE USER

        PCTUSED 95

        PCTFREE 5

        INITRANS 1

        MAXTRANS 255

        STORAGE (

        INITIAL 7312K

        NEXT 80K

        MINEXTENTS 1

        MAXEXTENTS 2147483645

        PCTINCREASE 0

        FREELISTS 1

        FREELIST GROUPS 1

        BUFFER_POOL DEFAULT

        )

        NOLOGGING

        NOCACHE

        NOPARALLEL;

        SQL>CREATE INDEX USER.I_PAY_STAFFID ON USER.PAY

        (STAFFID)

        NOLOGGING

        TABLESPACE USER

        PCTFREE 5

        INITRANS 2

        MAXTRANS 255

        STORAGE (

        INITIAL 1936K

        NEXT 80K

        MINEXTENTS 1

        MAXEXTENTS 2147483645

        PCTINCREASE 0

        FREELISTS 1

        FREELIST GROUPS 1

        BUFFER_POOL DEFAULT

        )

        NOPARALLEL;

        SQL>CREATE UNIQUE INDEX USER.PK_PAY_ID ON USER.PAY

        (PAYID)

        NOLOGGING

        TABLESPACE USER

        PCTFREE 5

        INITRANS 2

        MAXTRANS 255

        STORAGE (

        INITIAL 1120K

        NEXT 80K

        MINEXTENTS 1

        MAXEXTENTS 2147483645

        PCTINCREASE 0

        FREELISTS 1

        FREELIST GROUPS 1

        BUFFER_POOL DEFAULT

        )

        NOPARALLEL;

        SQL>ALTER TABLE USER.PAY ADD (

        FOREIGN KEY (STAFFID)

        REFERENCES USER.STAFF (STAFFID));

        SQL>ALTER TABLE USER.DEPOSITCLASSIFY ADD

        CONSTRAINT FK_DEPOSITCLASSIFY2

        FOREIGN KEY (PAYID)

        REFERENCES USER.PAY (PAYID) ;

        SQL>ALTER TABLE USER.DEPOSITCREDITLOG ADD

        CONSTRAINT FK_DEPOSITCREDITLOG2

        FOREIGN KEY (PAYID)

        REFERENCES USER.PAY (PAYID) ;

        SQL>ALTER FUNCTION "USER"."GENERATEPAYNO" COMPILE ;

        SQL>ALTER PROCEDURE "USER"."ENGENDERPRVPAY" COMPILE ;

        SQL>ALTER PROCEDURE "USER"."ISAP_ENGENDERPRVPAY" COMPILE ;

        SQL>ALTER PROCEDURE "USER"."SPADDCREDITDEPOSIT" COMPILE ;

        SQL>ALTER PROCEDURE "USER"."SPADDDEPOSITWITHOUTCARD" COMPILE ;

        SQL>ALTER PROCEDURE "USER"."SPADJUSTLWDEPOSIT" COMPILE ;

        ……

        然后将导出的表PAY_X的dmp文件导入一个临时的数据库中,然后在临时数据库中将其表名重新命名为PAY,再按表模式将其导出。

        imp USER/USER file= PAY_x.dmp tables=PAY ignore=y

        SQL>rename PAY_X to PAY;

        $ exp USER/USER file=PAY.dmp tables=PAY

        最后将这个dmp文件导入正式的生产数据库中即可。

        以上的过程在重建好PAY表后整个应用就恢复正常了,而重命名表后重建表的时间是非常之短的,我测试的时间大概是在几分钟之内就可以做完了,新数据就可以插入表了,剩下的工作就是将旧的数据导入数据库,这个工作的时间要求上就没有那么高了,因为应用已经正常了,一般来说利用晚上业务不忙的时候都可以把一张表的数据导入完成的。

        以上的六种清除行迁移的方法各有各自的优缺点,分别适用于不同的情况下使用,利用以上的几种清除行迁移的方法基本上就能完全清除掉系统中的存在的行迁移了,当然,具体的生产环境中还需要具体问题具体分析的,针对不同类型的系统,系统中不同特点的表采用不同的清除方法,尽量的减少停数据库的时间,以保证应用的不间断稳定运行。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件