如何从大型 table 中部分更新数百万条记录

How to partially update millions of records from a large table

我有一个名为 Employee 的 table,为了让问题简短,我没有在这里粘贴所有列,但例如为了让我们假设 desc 员工如下:

EMPNO      NOT NULL NUMBER(4)    
FIRST_NAME          VARCHAR2(10) 
LAST_NAME           VARCHAR2(10) 
SALARY              NUMBER(24)   
HIREDATE            DATE         
DEPT_ID              VARCHAR2(20) 
ELIGIBILITY         VARCHAR(2)

table 包含超过 5 亿条记录,我需要 运行 根据以下 where 子句对其进行更新:

update employee set ELIGIBILITY = 'N' where DEPT_ID IN 'INS, BAN, AUT';

现在当前更新需要超过24小时。

我在一些论坛上在线阅读,在这种情况下你应该

  1. 插入临时文件 table,不记录 -> 关于第一步,我有 2 个问题:

    a) 如果我选择插入新的 table

    ,我需要知道如何进行无日志记录部分

    b) 我是否必须编写两个单独的插入:一个用于插入符合条件的记录,另一个用于插入其余记录?

  2. 在新的 table 上并行创建索引和约束 -> 根据我所阅读的内容,这是并行创建索引的命令

    CREATE INDEX {new_index} ON employee({column_name}) PARALLEL 35 NOLOGGING;

-- 如有错误请指正

  1. 删除旧的table
  2. 重命名新的 table。

正如我已经提到的,我只需要更新符合条件的某些行,而不是全部。我将如何使用上述推荐的解决方案来做到这一点。

更新

您的更新语句将不起作用。正确的语法是

update employee 
    set ELIGIBILITY = 'N' 
    where DEPT_ID IN ('INS', 'BAN', 'AUT');

插入

A temp table 听起来很奇怪,因为 Oracle 有一个叫做 temporary table 的东西,但你可能不要使用临时 table 因为在这种情况下,您的数据将在您注销后丢失。所以让我们称它为辅助table.

CREATE TABLE auxtable
...
)
NOLOGGING;

将创建一个 table 有资格进行无日志记录操作。但前提是table空间甚至整个数据库都处于强制日志记录模式。

您现在只使用一个 INSERT 语句来插入数据 - 它必须提供适当的数据:

INSERT /*+APPEND */ INTO AUXTABLE(
    EMPNO,
    FIRST_NAME,
    LAST_NAME,
    SALARY,
    HIREDATE,  
    DEPT_ID,
    ELIGIBILITY)
SELECT
    EMPNO,
    FIRST_NAME,
    LAST_NAME,
    SALARY,
    HIREDATE,  
    DEPT_ID,
    DECODE(DEPT_ID,
        'INS', 'N',
        'BAN', 'N',
        'AUT', 'N',
        ELIGIBILITY
        )
FROM EMPLOYEE;

APPEND 提示建议 Oracle 在 table 上启用插入 NOLOGGING 模式。

索引

创建索引后,您应该更改索引的并行子句

ALTER INDEX {new_index} NOPARALLEL;

或源 table 中的索引使用的值。

您可以使用 Oracle Grid Control 或 SQL-Developer 等图形工具来生成 table 的 sql 提取物,或者您可以使用 expdp/impdp 来生成一个 sql 文件。

$ expdp myuser content=metadata_only tables=myuser.MYTABLE DUMPFILE='mydump.dp'

Export: Release 11.2.0.4.0 - Production on Sun Jan 01 01:00:00 2017

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.
Password:

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Starting "MYUSER"."SYS_EXPORT_TABLE_01":  myuser/******** content=metadata_only tables=myuser.MYTABLE DUMPFILE=mydump.dp
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Master table "MYUSER"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for MYUSER.SYS_EXPORT_TABLE_01 is:
  /mypath/mydump.dp



$ impdp myuser sqlfile=mytable.sql  tables=myuser.MYTABLE DUMPFILE='mydump.dp'

Import: Release 11.2.0.4.0 - Production on Sun Jan 01 01:00:10 2017

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.
Password:

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Master table "MYUSER"."SYS_SQL_FILE_TABLE_01" successfully loaded/unloaded
Starting "MYUSER"."SYS_SQL_FILE_TABLE_01":  myuser/******** sqlfile=mytable.sql tables=myuser.MYTABLE DUMPFILE=mydump.dp
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Job "MYUSER"."SYS_SQL_FILE_TABLE_01" successfully completed at Sun Jan 01 01:00:15 2017 elapsed 0 00:00:05

The Sqlfile will be here:
/mypath/mytable.sql