オラクルバージョンは次のようです。
UKJA@ukja1021> select * from v$version where rownum = 1
2 ;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
テーブルを作ります。C1列について自然に整列になっている形態です。
UKJA@ukja1021> create table t1
2 as select level as c1
3 from dual
4 connect by level <= 100000
5 -- order by dbms_random.random
6 -- how the table is ordered may affect the result
7 ;
Table created.
テーブルの全ての行をフェッチするもっとも単純な形態の並列実行です。
UKJA@ukja1021> begin
2 for c in ( select /*+ parallel(t1,4)*/ * from t1) loop
3 null;
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed.
その結果をV$PQ_TQSTATビューを通じて観察してみます。
ed pq_stat.sql
col process format a10
col server_type format a10
select dfo_number, tq_id, server_type, process,
num_rows, bytes, avg_latency, waits, timeouts
from v$pq_tqstat
order by 1, 2, 3, 4, 5
;
その結果は次のようです。
UKJA@ukja1021> @pq_stat
DFO_NUMBER TQ_ID SERVER_TYP PROCESS NUM_ROWS BYTES AVG_LATENCY
---------- ---------- ---------- ---------- ---------- ---------- -----------
WAITS TIMEOUTS
---------- ----------
1 0 Consumer QC 100000 595112 0
223 64
1 0 Producer P000 5913 33710 0
3 0
1 0 Producer P001 40870 243406 0
21 0
1 0 Producer P002 7884 45733 0
4 0
1 0 Producer P003 45333 272263 0
23 0
Elapsed: 00:00:00.01
四つのスレーブプロセスがテーブルからデータを読み込む生産者(Producer)で動作しました。驚いたことにP001、P003二つのプロセスが大部分のデータを読み込み、残りの二つは一部のデータだけを読み込みました。スレーブプロセスの間にデータを公平に読み込んでいないと言えます。こんな現状ができたら並列実行の性能が考えより高くない結果になってしまいます。
ORDER BY句を利用して整列を修行したらもっと深刻な結果が出ます。
UKJA@ukja1021> begin
2 for c in ( select /*+ parallel(t1,4)*/ * from t1 order by c1) loop
3 exit;
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.07
UKJA@ukja1021>
UKJA@ukja1021> @pq_stat
DFO_NUMBER TQ_ID SERVER_TYP PROCESS NUM_ROWS BYTES AVG_LATENCY
---------- ---------- ---------- ---------- ---------- ---------- -----------
WAITS TIMEOUTS
---------- ----------
1 0 Consumer P000 1972 9925 0
9 2
1 0 Consumer P001 1971 10018 0
9 3
1 0 Consumer P002 1971 10018 0
8 2
1 0 Consumer P003 94086 565403 0
116 47
1 0 Producer P004 31015 183753 0
24 3
1 0 Producer P005 21681 129330 0
17 4
1 0 Producer P006 27594 165130 0
22 5
1 0 Producer P007 19710 117279 0
14 2
1 0 Ranger QC 372 3789 0
3 1
1 1 Consumer QC 100 1927 0
67 23
1 1 Producer P000 1166 5782 0
14 3
1 1 Producer P001 1146 5780 0
14 3
1 1 Producer P002 1146 5781 0
13 2
1 1 Producer P003 1146 5781 0
122 48
14 rows selected.
四つのプロセス(P004 ~ P007)が生産者(Producer)でテーブルからデータを読み込むし四つのプロセス(P000 ~ P003)が消費者(Consumer)で整列を行いますが、その分布がたいへん良くないです。四つ目のプロセスであるP003が大部分の作業(94%、10,000件中94,086件)を行うのが分かります。このままなら並列実行のメリットはほとんどないと言えます。
こんな現状は索引を生成する時も同じです。索引の生成は内部的に整列作業を行います。次にその結果があります。
UKJA@ukja1021> create index t1_n1 on t1(c1) parallel 4;
Index created.
UKJA@ukja1021> @pq_stat
DFO_NUMBER TQ_ID SERVER_TYP PROCESS NUM_ROWS BYTES AVG_LATENCY
---------- ---------- ---------- ---------- ---------- ---------- -----------
WAITS TIMEOUTS
---------- ----------
1 0 Consumer P000 100000 1807692 0
4 1
1 0 Consumer P001 0 80 0
4 1
1 0 Consumer P002 0 80 0
4 1
1 0 Consumer P003 0 80 0
4 1
1 0 Producer P004 11826 212999 0
8 1
1 0 Producer P005 38899 705092 0
26 4
1 0 Producer P006 11826 213097 0
7 0
1 0 Producer P007 37449 676904 0
29 6
1 0 Ranger QC 0 160 0
5 1
1 1 Consumer QC 4 1272 0
4 1
1 1 Producer P000 1 318 0
0 0
1 1 Producer P001 1 318 0
0 0
1 1 Producer P002 1 318 0
0 0
1 1 Producer P003 1 318 0
0 0
14 rows selected.
今度はP000プロセスが全ての整列作業を行いました。並列作業のメリットはないと言えます。
こんな現状はデータの整列程度とも関連があるようです。次のようにテーブルにランダムでデータが入るように変えてみます。
UKJA@ukja1021> create table t1
2 as select level as c1
3 from dual
4 connect by level <= 100000
5 order by dbms_random.random -- !!
6 -- how the table is ordered may affect the result
7 ;
Table created.
この場合には四つのスレーブプロセスがほとんど公平に4等分して整列作業を行います。最高の理想的な場合だと言えます。
UKJA@ukja1021> begin
2 for c in ( select /*+ parallel(t1,4)*/ * from t1 order by c1) loop
3 exit;
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.06
UKJA@ukja1021>
UKJA@ukja1021> @pq_stat
DFO_NUMBER TQ_ID SERVER_TYP PROCESS NUM_ROWS BYTES AVG_LATENCY
---------- ---------- ---------- ---------- ---------- ---------- -----------
WAITS TIMEOUTS
---------- ----------
1 0 Consumer P000 23570 132528 0
39 13
1 0 Consumer P001 27176 164544 0
65 16
1 0 Consumer P002 27655 167454 0
50 18
1 0 Consumer P003 21599 130778 0
60 14
1 0 Producer P004 17739 105608 0
15 4
1 0 Producer P005 29044 173021 0
30 10
1 0 Producer P006 21681 129097 0
20 4
1 0 Producer P007 31536 187718 0
23 5
1 0 Ranger QC 372 4546 0
1 0
1 1 Consumer QC 100 1927 0
67 24
1 1 Producer P000 1166 5782 0
44 14
1 1 Producer P001 955 5782 0
70 17
1 1 Producer P002 955 5780 0
56 20
1 1 Producer P003 954 5777 0
66 16
14 rows selected.
하지만 인덱스를 생성할 경우에는 여전히 같은 문제가 발생합니다.
UKJA@ukja1021> create index t1_n1 on t1(c1) parallel 4;
Index created.
Elapsed: 00:00:00.54
UKJA@ukja1021>
UKJA@ukja1021> @pq_stat
DFO_NUMBER TQ_ID SERVER_TYP PROCESS NUM_ROWS BYTES AVG_LATENCY
---------- ---------- ---------- ---------- ---------- ---------- -----------
WAITS TIMEOUTS
---------- ----------
1 0 Consumer P000 100000 1807712 0
4 1
1 0 Consumer P001 0 80 0
4 1
1 0 Consumer P002 0 80 0
4 1
1 0 Consumer P003 0 80 0
4 1
1 0 Producer P004 15768 285122 0
10 0
1 0 Producer P005 32986 596372 0
25 0
1 0 Producer P006 17739 320856 0
12 1
1 0 Producer P007 33507 605762 0
22 1
1 0 Ranger QC 0 160 0
1 0
1 1 Consumer QC 4 1272 0
3 1
1 1 Producer P000 1 318 0
0 0
1 1 Producer P001 1 318 0
0 0
1 1 Producer P002 1 318 0
0 0
1 1 Producer P003 1 318 0
0 0
14 rows selected.
上記の現状を見ると整列作業を並列に修行するコードの一部分にロジックの誤りがあると考えられます。V$PQ_TQSTATビューではなければこんな現状を観察するのは易しくないです。機会がある時ぜひ活用してみるのをお勧めします。
この現状に対するもっとも詳しい説明は次のURLを参照してください。
No comments:
Post a Comment