再上一篇:14.1何时使用并行执行
上一篇:14.2并行查询
主页
下一篇:14.4并行DDL
再下一篇:14.5并行恢复
文章列表

14.3并行DML

Oracle 9i 10g编程艺术:深入数据库体系结构

Oracle 文档将并行DML(PDML)一词的范围限制为只包括INSERT、UPDATE、DELETE和MERGE(不像 平常的DML那样还包括SELECT)。在 PDML期间,Oracle可以使用多个并行执行服务器来执行INSERT、UPDATE、 DELETE或MERGE,而不是只利用一个串行进程。在一个有充足I/O带宽的多CPU主机上,对于大规模的DML 操作,可能会得到很大的速度提升。
不过,不能把 PDML当成提高OLTP应用速度的一个特性。如前所述,并行操作设计为要充分、完全地 利用一台机器上的所有资源。通过这种设计,一个用户可以完全使用机器上的所有磁盘、CPU和内存。在 某些数据仓库中(有大量数据,而用户很少),这可能正是你想要的。而在一个OLTP系统中(大量用户都 在做很短、很快的事务),可能就不能希望如此了,你不想让用户能够完全占用机器资源。
这听上去好像有些矛盾:我们使用并行查询是为了扩缩,它怎么可能是不可扩缩的呢?不过要知道, 应用到一个OLTP系统时,这种说法确实很正确。并行查询不能随着并发用户数的增加而扩展。并行查询设 计为允许一个会话能像100个并发会话一样生成同样多的工作。但在OLTP系统中,我们确认不希望一个用 户生成100个用户的工作。
PDML在大型数据仓库环境中很有用,它有利于大量数据的批量更新。类似于Oracle执行的分布式查 询,PDML操作采用同样的方式执行,即每个并行执行服务器相当于一个单独数据库实例中的一个进程。表
的每一部分(每一片)由一个单独的线程利用其自己的独立事务来修改(相应地,这个线程可能有自己的 undo段)。这些事务都结束后,会执行一个相当于快速2PC的过程来提交这些单独的独立事务。图14-2展 示了使用4 个并行执行服务器的并行更新。每个并行执行服务器都有其自己独立的事务,这些事务要么都 由PDML协调会话提交,要么无一提交。
实际上,我们可以观察到为并行执行服务器创建的各个独立事务。在此还是使用前面的两个会话。在 SID=162的会话中,我们显式地启用了并行DML。在这方面,PDML有别于并行查询;除非显式地请求PDML, 否则不能执行PDML。
big_table@ORA10GR1> alter session enable parallel dml;
Session altered.


图14-2 并行更新(PDML)示意图 这个表是“并行的“,但与并行查询不同,这对于PDML还不够。之所以要显式地在会话中启用 PDML,
原因是PDML存在一些相关的限制,我会在介绍完这个例子之后列出这些限制。
在这个会话中,下面执行一个批量 UPDATE,由于表已经“启用并行 DML“(enable parallel dml), 所以实际上这会并行执行:
big_table@ORA10GR1> update big_table set status = 'done';

在另一个会话中,我们将V$SESSION联结到V$TRANSACTION,来显示对应这个PDML操作的活动会话,

并显示这些会话的独立事务信息:
ops$tkyte@ORA10GR1> select a.sid, a.program, b.start_time, b.used_ublk,
2 b.xidusn ||'.'|| b.xidslot || '.' || b.xidsqn trans_id
3 from v$session a, v$transaction b
4 where a.taddr = b.addr
5 and a.sid in ( select sid
6 from v$px_session
7 where qcsid = 162 )
8 order by sid
9 /
SID PROGRAM START_TIME USED_UBLK TR ANS_ID
---- --------------------------------------- ------------------------ --------
---------- ------------
136 oracle@dellpe (P009) 08/03/05 14:28:17 6256
18.9.37
137 oracle@dellpe (P013) 08/03/05 14:28:17 6369
21.39.225
138 oracle@dellpe (P015) 08/03/05 14:28:17 6799
24.16.1175
139 oracle@dellpe (P008) 08/03/05 14:28:17 6729
15.41.68
140 oracle@dellpe (P014) 08/03/05 14:28:17 6462
22.41.444
141 oracle@dellpe (P012) 08/03/05 14:28:17 6436
20.46.46
142 oracle@dellpe (P010) 08/03/05 14:28:17 6607

19.44.37
143 oracle@dellpe (P007) 08/03/05 14:28:17 1
17.12.46
144 oracle@dellpe (P006) 08/03/05 14:28:17 1
13.25.302
145 oracle@dellpe (P003) 08/03/05 14:28:17 1
1.21.1249
146 oracle@dellpe (P002) 08/03/05 14:28:17 1
14.42.49
147 oracle@dellpe (P005) 08/03/05 14:28:17 1
12.18.323
150 oracle@dellpe (P011) 08/03/05 14:28:17 6699
23.2.565
151 oracle@dellpe (P004) 08/03/05 14:28:17 1
16.26.46
152 oracle@dellpe (P001) 08/03/05 14:28:17 1
11.13.336
153 oracle@dellpe (P000) 08/03/05 14:28:17 1
2.29.1103
162 sqlplus@dellpe (TNS V1-V3) 08/03/05 14:25:46 2 3.
13.2697
17 rows selected.
可以看到,与并行查询表相比,这里发生了更多事情。这个操作上有17个进程,而不像前面只有9

个进程。这是因为:开发的计划中有一步是更新表,另外还有一些独立的步骤用于更新索引条目。通过查 看从DBMS_XPLAN得到解释计划输出(我们对这个输出进行了编辑,去掉了尾部几列,以便这个输出能在一 页的篇幅内放下),可以看到以下结果:
-------------------------------------------------------------------------------------
| Id | Operation | Name
|
-------------------------------------------------------------------------------------
| 0 | UP

DATE STATEMENT | |
| 1 | PX COORDINATOR | |
| 2 | PX SEND QC (RANDOM) | :TQ10001 |
| 3 | INDEX MAINTENANCE | BIG_TABLE |
| 4 | PX RECEIVE | |
| 5 | PX SEND RANGE | :TQ10000 |
| 6 | UPDATE
| BIG_TABLE |
| 7 | PX BLOCK ITERATOR | |
| 8 | TABLE ACCESS FULL | BIG_TABLE
|
-------------------------------------------------------------------------------------
由于PDML采用的一种伪分布式的实现,因此存在一些限制:
PDML操作期间不支持触发器。在我看来,这是一个很合理的限制,因为触发器可能会向更 新增加大量开销,而你使用PDML的本来目的是为了更快一些,这两方面是矛盾的,不能放在一 起。
PDML期间,不支持某些声明方式的引用完整性约束,因为表中的每一片(部分)会在单独 的会话中作为单独的事务进行修改。例如,PDML操作不支持自引用完整性。如果真的支持自引 用完整性,可能会出现死锁和其他锁定问题。
在提交或回滚之前,不能访问用PDML修改的表。
PDML不支持高级复制(因为复制特性的实现要基于触发器)。 不支持延迟约束(也就是说,采用延迟模式的约束)。
如果表是分区的,PDML只可能在有位图索引或LOB列的表上执行,而且并行度取决于分区 数。在这种情况下,无法在分区内并行执行一个操作,因为每个分区只有一个并行执行服务器 来处理。
执行PDML时不支持分布式事务。 PDML不支持聚簇表。
如果违反了上述任何一个限制,就会发生下面的某种情况:语句会串行执行(完全不涉及并行化), 或者会产生一个错误。例如,如果对表T执行PDML,然后在结束事务之前试图查询表T,就会收到一个错 误。