sql - 将大量数据从一个表迁移到另一个表的技巧?
问题描述
我们必须把一张桌子分成两张。
我们当前工作的脚本如下所示:
- 禁用新表的约束
INSERT INTO newTable1 SELECT... FROM oldTable
INSERT INTO newTable2 SELECT... FROM oldTable WHERE fieldX IS NOT NULL
- 重新启用约束
与此同时,我们还研究了并行性的使用(到目前为止,在我们的测试中,由于某种原因没有任何收获......)。
除此之外,我们还能用什么来在 PROD 中进行安全快速的迁移?
解决方案
提高大表插入性能的两个主要工具是直接路径写入和并行性,它们可以很好地协同工作。
直接路径写入将数据直接放在数据文件中,并绕过创建额外的 REDO 和 UNDO 数据。此功能显着减少了 IO,但这意味着您的新表要等到下一次完整备份之后才能恢复。
并行可以使用额外的 CPU 和 IO 资源来显着提高性能。但正如 pmdba 所说,有很多奇怪的要求和原因导致并行性无济于事。最常见的问题是不正确地使用提示而不使用直接路径写入。并行读取很容易,但要启用并行写入,则需要直接路径写入。
在您花一天时间尝试阅读和理解VLDB 和分区指南的使用并行执行章节之前,有一种简单的方法可以尝试和测试这两个功能。如果幸运的话,您所需要的只是下面的代码,您甚至可能不需要费心禁用和重新启用约束:
alter session enable parallel dml;
insert /*+ parallel(8) append */ into newtable select * from oldtable;
commit;
如果这不起作用,请查看说明计划,您应该会看到如下内容:
alter session enable parallel dml;
explain plan for insert /*+ parallel(8) append */ into newtable select * from oldtable;
select * from table(dbms_xplan.display);
Plan hash value: 1569336347
----------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 | 13 | 2 (0)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10000 | 1 | 13 | 2 (0)| 00:00:01 | Q1,00 | P->S | QC (RAND) |
| 3 | LOAD AS SELECT (HYBRID TSM/HWMB)| NEWTABLE | | | | | Q1,00 | PCWP | |
| 4 | OPTIMIZER STATISTICS GATHERING | | 1 | 13 | 2 (0)| 00:00:01 | Q1,00 | PCWP | |
| 5 | PX BLOCK ITERATOR | | 1 | 13 | 2 (0)| 00:00:01 | Q1,00 | PCWC | |
| 6 | TABLE ACCESS FULL | OLDTABLE | 1 | 13 | 2 (0)| 00:00:01 | Q1,00 | PCWP | |
----------------------------------------------------------------------------------------------------------------------------
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
- Degree of Parallelism is 8 because of hint
在说明计划中查找四个关键项:“LOAD AS SELECT”而不是“LOAD CONVENTIONAL”意味着您正在使用直接路径写入,“TABLE ACCESS FULL”上方的“PX”操作意味着您正在使用并行读取,“ “LOAD AS SELECT”上方的“PX”操作意味着您正在使用并行写入,“并行度”告诉您请求了多少并行线程。
如果缺少这些项目中的任何一个,请调查“注释”部分,它通常会解释为什么您没有得到您所要求的。如果您仍然遇到问题,请将完整的解释计划以文本形式发布,我们可以帮助解决问题。
推荐阅读
- javascript - JavaScript 网格复制为字符串
- javascript - 如何记住溢出的滚动位置:滚动div?
- windows - WIN 10 PostgreSQL DB symbols are unreadable
- python - python 3.5 on Ubuntu 16.04 has dict syntax error for installed ackage?
- python - Save an image or several files what my telegram bot gets, to a specific directory
- c++ - Cast `size_t[]` to `char *` without C-style casting or `reinterpret_cast`
- javascript - Firebase auth - 登录然后重定向到应用程序 - 如何获取用户
- python - Python scrapy middleware not working as expected
- c# - 向数据库中插入数据失败
- ios - 无法打开,因为您无权查看 - React Native - Expo?