如何从大型 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小时。
我在一些论坛上在线阅读,在这种情况下你应该
插入临时文件 table,不记录
-> 关于第一步,我有 2 个问题:
a) 如果我选择插入新的 table
,我需要知道如何进行无日志记录部分
b) 我是否必须编写两个单独的插入:一个用于插入符合条件的记录,另一个用于插入其余记录?
在新的 table 上并行创建索引和约束
-> 根据我所阅读的内容,这是并行创建索引的命令
CREATE INDEX {new_index} ON employee({column_name}) PARALLEL 35 NOLOGGING;
-- 如有错误请指正
- 删除旧的table
- 重命名新的 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
我有一个名为 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小时。
我在一些论坛上在线阅读,在这种情况下你应该
插入临时文件 table,不记录 -> 关于第一步,我有 2 个问题:
a) 如果我选择插入新的 table
,我需要知道如何进行无日志记录部分b) 我是否必须编写两个单独的插入:一个用于插入符合条件的记录,另一个用于插入其余记录?
在新的 table 上并行创建索引和约束 -> 根据我所阅读的内容,这是并行创建索引的命令
CREATE INDEX {new_index} ON employee({column_name}) PARALLEL 35 NOLOGGING;
-- 如有错误请指正
- 删除旧的table
- 重命名新的 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