RAC 的一大优点就是可以跨节点进行并行计算, 那么如何控制并行运算? 这就是这篇文章要讨论的内容.
10 g 中:
合理设置跨节点并行, 需要先设置一些参数:
instance_groups: 这个参数主要是设置该节点实例是否属于某一个实例组. 每个节点可以设置多个不同的实例组名, 实例组名用逗号隔开.
parallel_instance_group 设置的值为 instance_groups 里面设置的值, 表明这个节点上面进行的并行操作可以跨越哪些实例组.
- alter system set instance_groups='dw','dw1','dw123','dw124','dw134' scope=spfile sid='dwrac1';
- alter system set instance_groups='dw','dw2','dw123','dw124','dw234' scope=spfile sid='dwrac2';
- alter system set instance_groups='dw','dw3','dw123','dw134','dw234' scope=spfile sid='dwrac3';
- alter system set instance_groups='dw','dw4','dw124','dw134','dw234' scope=spfile sid='dwrac4';
以上参数分别为 4 个节点定义了 5 个 instance group, 有的 group 包含多个节点, 有的 group 只包含一个节点.
一, 跨所有节点执行
分两种情况进行测试: instance_groups 包含所有节点和 instance_groups 只包含一个节点.
1. instance_groups 包含所有节点
1). 节点 2 参数设置情况
- admin@dwrac2> show parameter instance_group
- NAME TYPE VALUE
- ------------------------------------ ----------- ------------------------------
instance_groups string dw, dw2, dw123, dw124, dw234
parallel_instance_group string
只定义了 instance_groups, 不设置 parallel_instance_group.
前面我们设置过, dw 这个 instance_group 包含了所有的节点.
2). 在节点 2 发出查询
admin@dwrac2> select /*+ parallel(a,128) */count(1) from testuser.big_table a;
3). 另开一个窗口查询并行进程情况
- SQL> select INST_ID,COUNT(1) from gv$px_session p where (p.inst_id,p.sid) in (select s.inst_id,s.sid from gv$session s where s.username='ADMIN' and module like 'SQL*%') GROUP BY INST_ID;
- INST_ID COUNT(1)
- ---------- ----------
- 1 32
- 2 33
- 4 32
- 3 32
可以看到, 并行会话 (parallel slaves) 平均分配到 4 个节点上. 节点 2 多一个进程是因为它是并行查询的发起者, 额外的会话是发起会话, 也就是并行查询协调器(parallel query coordinator), 其余的是并行从属进程.
之所有能分配到 4 个节点上, 是因为 4 个节点都属于 dw 这个 instance group, 且都没有设定 parallel_instance_group.
2. instance_groups 只包含一个节点
1). 修改参数
admin@dwrac2> alter system set instance_groups='dw2' scope=spfile sid='dwrac2';
重启
- admin@dwrac2> show parameter instance_group
- NAME TYPE VALUE
- ------------------------------------ ----------- ------------------------------
- instance_groups string dw2
- parallel_instance_group string
不设置 parallel_instance_group, 且 instance_group=dw2 只包含节点 2.
2). 发出并行查询
admin@dwrac2> select /*+ parallel(a,128) */count(1) from testuser.big_table a;
3). 另开一个窗口查询并行进程情况
- SQL> select INST_ID,COUNT(1) from gv$px_session p where (p.inst_id,p.sid) in (select s.inst_id,s.sid from gv$session s where s.username='ADMIN' and module like 'SQL*%') GROUP BY INST_ID;
- INST_ID COUNT(1)
- ---------- ----------
- 1 32
- 2 33
- 4 32
- 3 32
可以看到, 即使是 instance_groups='dw2'只在节点 2 出现, 但是如果不设置 parallel_instance_group, 并行仍然可以跨越所有节点.
二, 跨部分节点执行
这部分分两种测试: 发出命令的节点属于 parallel_instance_group 的一员以及发出命令的节点不属于 parallel_instance_group
1. 发出命令的节点属于 parallel_instance_group 的一员
1). 在节点 2 修改参数
- admin@dwrac2> show parameter instance_group
- NAME TYPE VALUE
- ------------------------------------ ----------- ------------------------------
instance_groups string dw, dw2, dw123, dw124, dw234
- parallel_instance_group string
- admin@dwrac2> alter session set parallel_instance_group='dw2';
Session altered.
-- 这个设置的会强制并行操作只会属于 dw2 这个 instance group 的节点中执行.
-- 注意: parallel_instance_group 是大小写区分的, 如果用 alter session set parallel_instance_group=dw2, 则不会起任何并行进程, 因为不加单引号的话, 实际上载后台 dw2 会被转换成大写的 DW2, 不属于任何一个 instance group.
2). 在节点 2 发出同样的查询
admin@dwrac2> select /*+ parallel(a,128) */ count(1) from testuser.big_table a;
3). 另起一个会话查询并行情况
- SQL> select INST_ID,COUNT(1) from gv$px_session p where (p.inst_id,p.sid) in (select s.inst_id,s.sid from gv$session s where s.username='ADMIN' and module like 'SQL*%') GROUP BY INST_ID;
- INST_ID COUNT(1)
- ---------- ----------
- 2 129
可以看到, 因为只有节点 2 属于 dw2 这个 instance group, 所有并行会话都分布在节点 2 上.
2. 发出命令的节点不属于 parallel_instance_group
1) 在节点 2 修改参数
- admin@dwrac2> show parameter instance_group
- NAME TYPE VALUE
- ------------------------------------ ----------- ------------------------------
instance_groups string dw, dw2, dw123, dw124, dw234
- parallel_instance_group string
- admin@dwrac2> alter session set parallel_instance_group='dw1';
Session altered.
根据我们之前的设置, 只有节点 1 属于 dw1 这个 instance group.
2) 在节点 2 发出查询
admin@dwrac2> select /*+ parallel(a,128) */ count(1) from testuser.big_table a;
3) 新开一个会话查询并行进程信息
- SQL> select INST_ID,COUNT(1) from gv$px_session p where (p.inst_id,p.sid) in (select s.inst_id,s.sid from gv$session s where s.username='ADMIN' and module like 'SQL*%') GROUP BY INST_ID;
- INST_ID COUNT(1)
- ---------- ----------
- 1 128
- 2 1
可以看到, 除了并行查询协调器 (也就是发出查询命令的会话) 外, 所有并行进程都运行在节点 1 上.
这也说明了, 即使发出并行查询指令的节点不属于 parallel_instance_group, 但它仍然可以调用属于 parallel_instance_group 的节点资源.
admin@dwrac2> alter session set parallel_instance_group='dw134';
Session altered.
- Elapsed: 00:00:00.00
- admin@dwrac2> select /*+ parallel(a,128) */ count(1) from testuser.big_table a;
- SQL> select INST_ID,COUNT(1) from gv$px_session p where (p.inst_id,p.sid) in (select s.inst_id,s.sid from gv$session s where s.username='ADMIN' and module like 'SQL*%') GROUP BY INST_ID;
- INST_ID COUNT(1)
- ---------- ----------
- 1 42
- 2 1
- 4 42
- 3 44
总结一下:
1. RAC 可以通过 instance_groups 和 parallel_instance_group 来灵活控制如何跨节点进行并行运算.
2. parallel_instance_group 区分大小写. 如果设定的 parallel_instance_groups 值不属于整个 cluster 的任意一个 instance_groups 设定值, 则 Oracle 只会串行执行操作, 不会启用并行.
3. 如果不设定 parallel_instance_group, 不管 instance_group 如何设置, 并行可以跨越所有节点
4. 如果某个节点设定了有效的 parallel_instance_group, 则在该节点发出的并行操作可以运行在 parallel_instance_groups 包含的所有节点上, 不管 parallel_instance_groups 的节点是否包含发出命令的节点.
也就是说并行会话运行在那些节点只与 instance_groups 和 parallel_instance_groups 有关, 与命令在那个节点发出无关.
5. 一般建议设置好合适的 instance_groups, 但不要在系统级设定 parallel_instance_groups, 根据实际情况在会话级设置 parallel_instance_groups 参数.
6. 以下是一些例子及说明
- dwrac1.instance_groups='dw','dw1','dw123','dw124','dw134'
- dwrac2.instance_groups='dw','dw2','dw123','dw124','dw234'
- dwrac3.instance_groups='dw','dw3','dw123','dw134','dw234'
- dwrac4.instance_groups='dw','dw4','dw124','dw134','dw234'
dwrac1.parallel_instance_groups='' -- 节点 1 发起的并行计算请求的会话可跨越所有节点执行
dwrac1.parallel_instance_groups='dw' -- 节点 1 发起的并行计算请求的会话可跨越所有节点执行
dwrac1.instance_groups='dw1' -- 节点 1 发起的并行计算请求的会话只可在节点 1 执行
dwrac1.instance_groups='dw2' -- 节点 1 发起的并行计算请求的会话只可在节点 2 执行
dwrac2.instance_groups='dw134' ---- 节点 2 发起的并行计算请求的会话只可在节点 1/3/4 上执行
dwrac1.instance_groups='other' -- 不会启用并行
11 g 中:
11g 数据库中, 并行会话默认使用的是 shared pool 用于并行执行时的消息缓冲区,
并行过多时容易造成 shared pool 不足, 使数据库报 ORA-4031 错误. 将这个参数设置为
true, 使并行会话改为使用 large pool.
1,-- 调整 Px 操作使用 shared pool
alter system set "_px_use_large_pool"=true sid ='*' scope=spfile;
2,-- RAC 参数调整 parallel_force_local
该 11g 的新增参数, 用于将并行的 slave 进程限制在发起并行 SQL 的会话所在的
节点, 即避免跨节点并行产生大量的节点间数据交换和引起性能问题. 该参数取代 11g
之前的 instance_groups 和 parallel_instance_group 两个参数.
alter system set parallel_force_local=true sid='*' scope=spfile;
来源: http://www.linuxidc.com/Linux/2018-08/153359.htm