Oracle 并发查询

需要打开计时器的话可以参考

set timing on;

在开始之前需要强调的是

任何并发操作都是以硬件换速度, 如果没有足够的硬件不要轻易使用并发,另外如果是大访问量的网站系统请慎用,数据库并发查询一般还是用在夜晚的大批量batch批处理上

1. 直接改表

ALTER TABLE INO_ONCONFIG.LOOKUP_OPTIONS PARALLEL 4;

要关闭的话使用直接NOPARALLEL参数或者直接设置线程数为1好像也可以

ALTER TABLE INO_ONCONFIG.LOOKUP_OPTIONS NOPARALLEL;

ALTER TABLE INO_ONCONFIG.LOOKUP_OPTIONS PARALLEL 1;

2. 使用hint

需要注意的是如果需要指定schema名的话hint的时候需要把schema名去掉

select /*+ parallel(LOOKUP_OPTIONS 8) */ count(*) from INO_ONCONFIG.LOOKUP_OPTIONS;

下面我使用一个关联查询的sql来看看并行与非并行的区别

(我这里并发的消耗要比直接全表扫描join更大)

EXPLAIN PLAN FOR 
select   * from INO_OUTAGES.OUTAGE o
  join INO_OUTAGES.BASE_LOOKUP b on o.id=b.OUTAGE_ID;
SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));EXPLAIN PLAN FOR 
select /*+ parallel(o 4) */ /*+ parallel(b 4) */  * from INO_OUTAGES.OUTAGE o
  join INO_OUTAGES.BASE_LOOKUP b on o.id=b.OUTAGE_ID;
SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));

PX 进程: Parallel Execution Slaves

Parallel to Serial(P->S): 并发到串行

Parallel to Parallel(P->P):并发到并发

Parallel Combined with parent(PCWP): 同一个从属进程执行的并行操作,同时父操作也是并行的。

Parallel Combined with Child(PCWC): 同一个从属进程执行的并行操作,子操作也是并行的。

Serial to Parallel(S->P): 串行到并发

用户进程发起请求之后, oracle会使用一个QC进程(Query Coordinator)来协调这个用户进程与oracle进程之间的工作

它会决定这个请求的并发度,控制执行过程,汇总结果等 ( 上图中的PX COORDINATOR)

一般来说你只会有一个QC, 不过如果使用了类似UNIONALL这样的操作,就会出现多个QC

每个QC都包含一个树形结构, 这个树包含若干DFO节点(Data Flow Operator) , DFO是可以并行执行的单元, QC持有一到两组QSS(Query Slaves Set),每个QSS包含若干QS(Query Slaves),QSS会扮演生产者和消费者的角色,(每个QSS可能同为生产者,也可能同为消费者,也可能一个生产者一个消费者), 我们通常所说的并行度指的是一组QSS里并行的QS个数,所以如果oracle使用了两组QSS,那么实际运行的线程数会是并行度的两倍

TQ(table queue), 意为表队列。它是一个逻辑上的概念。在并行执行中,用TQ来实现query slave set 之间以及query slave set 和QC之间数据的传递和重新分布。可以简单认为就是存储并行执行过程中的中间结果的临时表

简单归纳一下

oracle进程

    -> 启动1个QC或者多个QC

          -> 每个QC = 一个DFO树

          -> 每个QC = 最多2个QSS (查看TQ列)

              -> 每个QSS = 若干QS

所以上图中

启动一个QC,也就是一个DFO树( 参考id 1 )

有两组QSS(TQ列的Q10,01和Q10,02) ( id 2,3,4,5 为Q10,02   id 9,10,11,12为Q10,01)

Q10,01为生产者 (它在执行TABLE ACCESS FULL和 PX BLOCK ITERATOR id 11,12) , Q10,01 先以并行的方式对OUTAGE table进行了全表扫描

同时, Q10,02在一开始也作为生产者扫描了BASE_LOOKUP 表, 然后转为消费者在id 03 处对两个结果集进行了join, 然后输出了合并后的结果

为了观察的更细致一些使用union all关键字可以得到两个QC的结果

EXPLAIN PLAN FOR 
select /*+ parallel(o 4) */ /*+ parallel(b 4) */  o.id,b.OUTAGE_ID,o.OUTAGE_TYPE from INO_OUTAGES.OUTAGE o
  left join INO_OUTAGES.BASE_LOOKUP b on o.id=b.OUTAGE_ID
union all
select /*+ parallel(o 4) */ /*+ parallel(h 4) */  h.id,h.OUTAGE_ID,o.OUTAGE_TYPE from INO_OUTAGES.OUTAGE o
  left join INO_OUTAGES.HISTORY h on o.id=h.OUTAGE_ID
;
SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));

Leave a Reply