在 Oracle 中的大表上将列类型从 varchar2 更改为数字的最快方法

kev*_*kev 2 oracle

我有一个包含 VARCHAR2 列的表,我必须将其更改为 NUMBER。

该表包含超过 3000 万行。

表定义:

CREATE TABLE EFF (
    MOD         VARCHAR2(6)     NOT NULL,
    MP          VARCHAR2(6)     NOT NULL,
    PROG        VARCHAR2(1)     NOT NULL,
    RNK         VARCHAR2(4)     NOT NULL,
    EFF_STS     VARCHAR2(1),
    EFF_PART    VARCHAR2(1),
    CONSTRAINT PK_EFF PRIMARY KEY (MOD, MP, PROG, RNK)
);
Run Code Online (Sandbox Code Playgroud)

我在 Oracle 11g 上用于更改RNK列类型的代码:

ALTER TABLE EFF ADD (NRNK NUMBER(5));
UPDATE EFF SET NRNK = TO_NUMBER(RNK);
ALTER TABLE EFF MODIFY (NRNK NUMBER(5) NOT NULL);
Run Code Online (Sandbox Code Playgroud)

然后我会修改主键并删除旧列:

ALTER TABLE EFF DROP PRIMARY KEY DROP INDEX;
ALTER TABLE EFF ADD CONSTRAINT PK_EFF PRIMARY KEY (MOD, MP, PROG, NRNK);
ALTER TABLE EFF DROP COLUMN RNK;
Run Code Online (Sandbox Code Playgroud)

UPDATE期很长,至少20分钟。什么可能是更快地做到这一点的最佳方法?

除了主键没有其他索引。

小智 5

我想,您可以使用并行操作:

并行 DML

让你的表支持并行操作:

ALTER TABLE EFF parallel;
Run Code Online (Sandbox Code Playgroud)

然后,您按照问题中的描述执行所有步骤。

并行 DDL + CTAS

CREATE TABLE temp_table_EFF
PARALLEL
AS
SELECT MOD, MP, PROG, TO_NUMBER(RNK), EFF_PART
  FROM EFF 
Run Code Online (Sandbox Code Playgroud)

然后你放下你的桌子:

DROP TABLE EFF;
Run Code Online (Sandbox Code Playgroud)

然后重命名临时表:

ALTER TABLE temp_table_EFF RENAME TO EFF;
Run Code Online (Sandbox Code Playgroud)

然后为这个新表添加索引:

ALTER TABLE EFF ADD CONSTRAINT PK_EFF PRIMARY KEY (MOD, MP, PROG, NRNK);
Run Code Online (Sandbox Code Playgroud)

我没有包含 30M 记录的表,所以我无法告诉你哪种方法更快。两个都试试。如果您认为不会有不错的性能改进,请尝试使用该NOLOGGING选项来禁止您的表生成重做信息。