Oracle并行操作——并行DML操作

2024-04-02 08:18

本文主要是介绍Oracle并行操作——并行DML操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

对大部分的OLTP系统而言,并行DML(PDML)的应用场景不多。大多数的PDML操作集中在下面几个场景下:

 

ü        系统移植,从旧系统中导入原始数据和基础数据;

ü        数据仓库系统Data Warehouse定期进行大批量原始数据导入和清洗;

ü        借助一些专门的工具,如sql loader,进行数据海量导入;

 

本篇主要介绍并行DML操作的一些细节和注意方面。

 

1、环境准备

 

Oracle并行操作前提两个条件,其一是盈余的软硬件资源,其二是海量的大数据量操作。

 

//操作系统和DB环境

SQL> select * from v$version where rownum<2;

 

BANNER

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

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

 

SQL> show parameter cpu_count;

 

NAME                                 TYPE                   VALUE

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

cpu_count                            integer                4

SQL>

 

//数据环境

SQL> select count(*) from t;

 

  COUNT(*)

----------

  10039808

 

Executed in 4.072 seconds

 

 

 

2、并行统计量收集

 

为了实现CBO的正常工作,我们通常要保证Oracle数据字典中保留有关于数据表完全的统计信息描述。统计信息包括数据行数、取值分布、离散程度等等指标。收集统计量是一项比较重要的工作。当数据表很大的时候,即使使用了比例抽样的方法,进行汇总统计的数据量也是很大。所以这种场合下,是可以应用到并行技术的。

 

在目前的Oracle版本中,通常是使用dbms_stats包进行统计量收集。相对于过去的analyze table xxx命令,dbms_stats包对于统计量收集更加完全,应对分区状况更好。在dbms_stats方法中,存在参数degree,表示并行度,可以直接指定希望的收集并行度。

 

 

--收集统计量,指定并行度

SQL> exec dbms_stats.gather_table_stats(user,'T',cascade => true,degree => 7);

PL/SQL procedure successfully completed

 

Executed in 15.32 seconds

 

 

系统使用15.32s的时间完成了收集。

 

在收集过程中,我们观察v$px_session和v$px_process两个视图的状态。检查并行伺服进程池的状况。

 

SQL> select * from v$px_process;

 

SERVER_NAME STATUS           PID SPID            SID    SERIAL#

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

P006        IN USE           100 19070982             35      50729

P001        IN USE            65 13107452            178      35585

P002        IN USE            73 9633888             184      25268

P003        IN USE            85 22478986            223      33339

P000        IN USE            63 18743314            500      16029

P004        IN USE            95 14221380            509      26446

P005        IN USE            99 23068708            510      20895

 

7 rows selected

 

 

系统依据并行度要求,分配了7个进程进行操作。

 

//并行会话信息

SQL> select * from v$px_session;

 

SADDR   SID    SERIAL#      QCSID  QCSERIAL#      DEGREE REQ_DEGREE

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

070000007D2BA680        500      16029        324      26152           7   7

070000007FE7EC70        178      35585        324      26152           7   7

070000007FE6D5D0        184      25268        324      26152           7   7

070000007FDFC2C0        223      33339        324      26152           7   7

070000007D2A0490        509      26446        324      26152           7   7

070000007D29D620        510      20895        324      26152           7    7

070000007FC94480         35      50729        324      26152           7    7

070000007D12FB00        324      26152        324             

(篇幅原因,有截取结果……)

8 rows selected

 

 

注意,在请求了并行度degree=7的情况下,Oracle根据CPU数量分配了7个并行slave进程进行操作。会话层面,七个slave进程分别对应七个会话信息进行并行操作。同时,存在一个额外会话(sid=324),充当全局协调者coordinator的角色。v$px_session中的qcsid字段含义为“Session serial number of the parallel coordinator”,就是并行操作中扮演协调者角色的进程。

 

 

如果不使用并行收集,只是简单的串行收集,我们查看一下效率情况。

 

 

//指定串行

SQL> exec dbms_stats.gather_table_stats(user,'T',cascade => true,degree => 1);

PL/SQL procedure successfully completed

 

Executed in 46.816 seconds

 

 

效果清晰可见,从原来的15s多的收集时间,放大为47s左右,几乎是三倍的损耗。

 

 

结论:对于统计量收集而言,如果作业时间可以避开业务高峰时间窗口,进行并行操作收集统计量还是一个不错的选择。

 

 

3、并行insert操作

 

下面进行并行insert操作,我们选择使用hint来进行并行控制。

 

//开启PDML的开关

SQL> alter session enable parallel dml;

Session altered

 

Executed in 0.016 seconds

 

使用hint,开启8个并行度进行insert操作。

 

 

--并行insert

SQL> insert /*+ parallel(t,8) */ into t select * from t;

10039808 rows inserted

 

Executed in 76.238 seconds

 

 

运行过程中,出现的并行操作过程如下。

 

//开启8个并行度;

SQL> select * from v$px_session;

 

SADDR                   SID    SERIAL#      QCSID  QCSERIAL#

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

070000007FFF52E0        361       3123        324      26152 

070000007FE84950        176      50028        324      26152

070000007FE7EC70        178      35508        324      26152  

070000007FE0AAF0        218       5994        324      26152 

070000007D29D620        510      20829        324      26152 

070000007D2A0490        509      26391        324      26152 

070000007FC94480         35      50615        324      26152  

070000007FFFAFC0        359      32516        324      26152  

070000007D12FB00        324      26152        324            

 

9 rows selected

 

SQL> select * from v$px_process;

SERVER_NAME STATUS           PID SPID                    SID SERIAL#

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

P006        IN USE           100 19005590                         35      50615

P001        IN USE            69 19398710                        176      50028

P002        IN USE            73 9633968                         178      35508

P003        IN USE            85 23068694                        218       5994

P007        IN USE           102 18743298                        359      32516

P000        IN USE            66 14221352                        361       3123

P005        IN USE            99 21233884                        509      26391

P004        IN USE            95 19071188                        510      20829

 

8 rows selected

 

 

此时,我们尝试抽取出执行计划。

 

//从shared_pool中尝试获取到指定的记录;

SQL> select sql_text, sql_id, version_count from v$sqlarea where sql_text like 'insert /*+ parallel(t,8) */%';

 

SQL_TEXT                        SQL_ID        VERSION_COUNT

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

insert /*+ parallel(t,8) */ into t select * from t   67wymm0jhw3gv             2

 

Executed in 0.234 seconds

 

 

利用sql_id,尝试抽取出shared_pool中的执行计划。

 

//抽取出执行计划,篇幅原因,有删节……

SQL> select * from table(dbms_xplan.display_cursor('67wymm0jhw3gv',format => 'advanced',cursor_child_no => 1));

PLAN_TABLE_OUTPUT

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

SQL_ID  67wymm0jhw3gv, child number 1

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

insert /*+ parallel(t,8) */ into t select * from t

Plan hash value: 4064487821

 

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

| Id  | Operation             | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |

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

|   0 | INSERT STATEMENT      |          |       |       |  2718 (100)|          |        |      |            |

|   1 |  PX COORDINATOR       |          |       |       |            |          |        |      |            |

|   2 |   PX SEND QC (RANDOM) | :TQ10000 |  5019K|   469M|  2718   (1)| 00:00:33 |  Q1,00 | P->S | Q

|   3 |    LOAD AS SELECT     |          |       |       |            |          |  Q1,00 | PCWP |            |

|   4 |     PX BLOCK ITERATOR |          |  5019K|   469M|  2718   (1)| 00:00:33 |  Q1,00 | PCWC |            |

|*  5 |      TABLE ACCESS FULL| T        |  5019K|   469M|  2718   (1)| 00:00:33 |  Q1,00 | PCWP |            |

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

Predicate Information (identified by operation id):

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

   5 - access(:Z>=:Z AND :Z<=:Z)

Note

-----

   - automatic DOP: Computed Degree of Parallelism is 8 because of degree limit

已选择66行。

 

已用时间:  00: 00: 00.40

 

 

如果不使用并行操作,进行如此规模的insert操作,会如何呢?

 

//使用noparallel的hint进行并行抑制;

 

SQL> insert /*+ noparallel */ into t select * from t;

10039808 rows inserted

 

Executed in 87.813 seconds

 

 

对应的执行计划如下:

 

 

SQL> select sql_text, sql_id, version_count from v$sqlarea where sql_text like 'insert /*+ noparallel */%';

 

SQL_TEXT                                SQL_ID VERSION_COUNT

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

insert /*+ noparallel */ into t select * from t    9u0xcrr3bcjs1             1

 

Executed in 0.234 seconds

 

 

 

SQL> select * from table(dbms_xplan.display_cursor('9u0xcrr3bcjs1',format => 'advanced',cursor_child_no => 0));

 

PLAN_TABLE_OUTPUT

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

SQL_ID  9u0xcrr3bcjs1, child number 0

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

insert /*+ noparallel */ into t select * from t

 

Plan hash value: 2153619298

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

| Id  | Operation                | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | INSERT STATEMENT         |        |       |       | 19601 (100)|          |

|   1 |  LOAD TABLE CONVENTIONAL |      |       |       |            |      |

|   2 |   TABLE ACCESS FULL      | T    |  5019K|   469M| 19601   (1)| 00:03:56 |

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

 

 

 

4、结论

 

本篇对PDML进行了简单的介绍,包括使用方法和并行度设置。由于篇幅原因,只介绍了并行insert和并行统计量的收集。并行update和delete本质相同,就不加以累述了。

 

最后,并行操作是一种带有特殊性的操作,绝对不要将其轻易作为经常性无监管下的操作

这篇关于Oracle并行操作——并行DML操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/869451

相关文章

Java Stream流与使用操作指南

《JavaStream流与使用操作指南》Stream不是数据结构,而是一种高级的数据处理工具,允许你以声明式的方式处理数据集合,类似于SQL语句操作数据库,本文给大家介绍JavaStream流与使用... 目录一、什么是stream流二、创建stream流1.单列集合创建stream流2.双列集合创建str

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

oracle 11g导入\导出(expdp impdp)之导入过程

《oracle11g导入导出(expdpimpdp)之导入过程》导出需使用SEC.DMP格式,无分号;建立expdir目录(E:/exp)并确保存在;导入在cmd下执行,需sys用户权限;若需修... 目录准备文件导入(impdp)1、建立directory2、导入语句 3、更改密码总结上一个环节,我们讲了

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo

sysmain服务可以禁用吗? 电脑sysmain服务关闭后的影响与操作指南

《sysmain服务可以禁用吗?电脑sysmain服务关闭后的影响与操作指南》在Windows系统中,SysMain服务(原名Superfetch)作为一个旨在提升系统性能的关键组件,一直备受用户关... 在使用 Windows 系统时,有时候真有点像在「开盲盒」。全新安装系统后的「默认设置」,往往并不尽编

Java Stream 并行流简介、使用与注意事项小结

《JavaStream并行流简介、使用与注意事项小结》Java8并行流基于StreamAPI,利用多核CPU提升计算密集型任务效率,但需注意线程安全、顺序不确定及线程池管理,可通过自定义线程池与C... 目录1. 并行流简介​特点:​2. 并行流的简单使用​示例:并行流的基本使用​3. 配合自定义线程池​示

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Python自动化处理PDF文档的操作完整指南

《Python自动化处理PDF文档的操作完整指南》在办公自动化中,PDF文档处理是一项常见需求,本文将介绍如何使用Python实现PDF文档的自动化处理,感兴趣的小伙伴可以跟随小编一起学习一下... 目录使用pymupdf读写PDF文件基本概念安装pymupdf提取文本内容提取图像添加水印使用pdfplum

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

使用Python的requests库来发送HTTP请求的操作指南

《使用Python的requests库来发送HTTP请求的操作指南》使用Python的requests库发送HTTP请求是非常简单和直观的,requests库提供了丰富的API,可以发送各种类型的HT... 目录前言1. 安装 requests 库2. 发送 GET 请求3. 发送 POST 请求4. 发送