MTU と他のプログラムを「名前付きパイプ」と呼ばれるものを使ってつなぐと、CSVデータをディスクへ書き/読みするI/Oが無くなるのでCSVファイルを介在させるよりも性能が向上します。
このトピックでは java言語で記述されたプログラムとMTUを名前付きパイプで直接つなぐ方法を具体的に説明します。
SCOTTスキーマでお馴染みのサンプルインスタンス表(EMP,DEPT,SALGRADE)を使い、読者がチュートリアルとして試すことが出来るよう配慮しました。
このトピックではjava言語のサンプルとして下記の2つを提供しています。
ファイル名 | 内容 |
---|---|
NamedPipeSingle.java | シングルスレッド版 |
NamedPipeMulti.java | マルチスレッド版 |
シングルスレッド版をMTUとともに動作させたときのイメージは下記の通りです。
NamedPipeSingleは名前付きパイプ経由でダイレクトに送られてくるCSVデータを一つ一つ画面へ表示します。
処理がシリアルに進むので、ある表のCSV表示処理が終わるまで次のCSV表示処理を開始することが出来ません。
すべての処理が終わるまでに掛かる時間は、それぞれの表を一つずつアンロードしたときの時間の合計です。
マルチスレッド版をMTUとともに動作させたときのイメージは下記の通りです。シングル版と重複している名称は省略しています。
NamedPipeMultiは名前付きパイプ経由でダイレクトに送られてくるCSVデータを一斉に画面へ表示します。
処理がパラレルに進むので、ある表のCSV表示処理が終わる前に次のCSV表示処理が開始されます。
すべての処理が終わるまでに掛かる時間は、それぞれの表を一つずつアンロードしたときの時間の合計を並列度で割った数より少し多くなります。
\\.\pipe\pipename
named_pipe://\\.\pipe\{C}.{X}
という文字列を指定することにより、出力データを名前付きパイプへ送ることが出来るようになります。
javac NamedPipeSingle.java javac NamedPipeMulti.java
コンパイルに失敗する場合は、環境変数 JAVA_HOME や PATH が正しいことをチェックしてみてください。
notepad env.bat
下記に示した環境変数の値を書き換えます。
環境変数名 | 出荷時初期値 | 書き換える値 |
---|---|---|
USERID | SYSTEM/MANAGER | SYSTEM/パスワード@DB別名 |
LISTTABLE | EMP,DEPT,SALGRADE | |
STDOUT | 0x0000 | 0x0001 |
STREAM_LOCATOR | named_pipe://\\.\pipe\{C}.{X} | |
SKIPSCR | true | |
EMBED_COLUMN_NAME | ,:”: |
次のようなメッセージが表示され製品コンポーネントがインストールされます。
C:\ProgramData\PLUMSIX\mtu_4.1\x64>install.bat Multi-threaded Unloader version 4.11 (c) 2003 Plumsix Co.,Ltd. All rights reserved. Windows 7 Professional Service Pack 1 (build 7601), 64-bit native Number of NUMA nodes: 1 Number of physical processor packages: 1 Number of processor cores: 2 Number of logical processors: 2 Number of processor L1/L2/L3 caches: 4/1/0 製品コンポーネントのインストールを実行します... クライアント・キャラクタセットID は 838 (JA16SJISTILDE) です。 ネット・サービス名:mtu01 へユーザ名:SYSTEM として接続します。 しばらくお待ちください... Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production With the Partitioning, OLAP and Data Mining options 接続先は SYSTEM@xxx (ネット・サービス名:mtu01) です。 サーバー・タイプは DEDICATED です。 監査接続IDは 4799234 です。 サーバーの日付時刻は 2012-10-24 18:34:09 です。 対象スキーマは SCOTT です。 以下の製品コンポーネントを SYSTEM スキーマへインストールしました。 APLDDP01 (PACKAGE), APLDDT01 (TABLE), APLDDT02 (TABLE), APLDDT03 (TABLE), APLDDT04 (TABLE) データベース接続用スクリプトを作成しました。C:\ProgramData\PLUMSIX\mtu_4.1\x64\input\_connect.sql アンインストール用スクリプトを作成しました。C:\ProgramData\PLUMSIX\mtu_4.1\x64\input\_drp_prod.sql パブリックシノニム作成用スクリプトを作成しました。C:\ProgramData\PLUMSIX\mtu_4.1\x64\input\_cre_pub_syn.sql パブリックシノニム削除用スクリプトを作成しました。C:\ProgramData\PLUMSIX\mtu_4.1\x64\input\_drp_pub_syn.sql 処理対象となった表の総数 : 5 ラウンドトリップ(回) : 28 出力バイト総数(kbytes) : 2.51 所要時間(秒) : 0.34 処理速度(kbytes/秒) : 7.44 正常終了しました。
これで準備が整いました。それでは実行してみましょう。
CD /d サンプルプログラムを格納したフォルダ
C:\ProgramData\PLUMSIX\mtu_4.1\x64>unload Multi-threaded Unloader version 4.11 (c) 2003 Plumsix Co.,Ltd. All rights reserved. Windows 7 Professional Service Pack 1 (build 7601), 64-bit native Number of NUMA nodes: 1 Number of physical processor packages: 1 Number of processor cores: 2 Number of logical processors: 2 Number of processor L1/L2/L3 caches: 4/1/0 表データファイル出力を実行します... #### 途中略 #### 空領域サイズチェックの閾値は 1024Mバイトです。 データファイルと制御ファイルを出力中です。[1561M] C:\ProgramData\PLUMSIX\mtu_4.1\x64\output ストリームの位置:named_pipe://\\.\pipe\{C}.{X} TableName : NumRows: Elapse:Rows/s:Bytes: B/s: Len DEPT : Executing
java プログラムがパイプ経由でCSVデータを受け取り始めるとデータを画面に表示します。
C:\TEMP\java_test>java NamedPipeSingle *** Start: \\.\pipe\EMP.dat *** "EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO" 7369,"SMITH","CLERK",7902,"19801217000000",800,,20 7499,"ALLEN","SALESMAN",7698,"19810220000000",1600,300,30 7521,"WARD","SALESMAN",7698,"19810222000000",1250,500,30 7566,"JONES","MANAGER",7839,"19810402000000",2975,,20 7654,"MARTIN","SALESMAN",7698,"19810928000000",1250,1400,30 7698,"BLAKE","MANAGER",7839,"19810501000000",2850,,30 7782,"CLARK","MANAGER",7839,"19810609000000",2450,,10 7839,"KING","PRESIDENT",,"19811117000000",5000,,10 7844,"TURNER","SALESMAN",7698,"19810908000000",1500,0,30 7900,"JAMES","CLERK",7698,"19811203000000",950,,30 7902,"FORD","ANALYST",7566,"19811203000000",3000,,20 7934,"MILLER","CLERK",7782,"19820123000000",1300,,10 *** End: \\.\pipe\EMP.dat *** *** Start: \\.\pipe\DEPT.dat *** "DEPTNO","DNAME","LOC" 10,"ACCOUNTING","NEW YORK" 20,"RESEARCH","DALLAS" 30,"SALES","CHICAGO" 40,"OPERATIONS","BOSTON" *** End: \\.\pipe\DEPT.dat *** *** Start: \\.\pipe\SALGRADE.dat *** "GRADE","LOSAL","HISAL" 1.E+00,7.E+02,1.2E+03 2.E+00,1.201E+03,1.4E+03 3.E+00,1.401E+03,2.E+03 4.E+00,2.001E+03,3.E+03 5.E+00,3.001E+03,9.999E+03 *** End: \\.\pipe\SALGRADE.dat ***
同時にハングしていたMTUが再開します。
データファイルと制御ファイルを出力中です。[1561M] C:\ProgramData\PLUMSIX\mtu_4.1\x64\output ストリームの位置:named_pipe://\\.\pipe\{C}.{X} TableName : NumRows: Elapse:Rows/s:Bytes: B/s: Len EMP : 12: 316.70: 0.: 727.: 2.: 60. DEPT : 4: 316.73: 0.: 124.: 0.: 31. SALGRADE : 5: 0.06: 87.: 152.:2666.: 30. 処理対象となった表の総数 : 3 ラウンドトリップ(回) : 83 出力バイト総数(kbytes) : 2.17 所要時間(秒) : 317.59 処理速度(kbytes/秒) : 0.01 正常終了しました。
データファイルと制御ファイルを出力中です。[1560M] C:\ProgramData\PLUMSIX\mtu_4.1\x64\output ストリームの位置:named_pipe://\\.\pipe\{C}.{X} TableName : NumRows: Elapse:Rows/s:Bytes: B/s: Len EMP : 12: 6.68: 1.: 727.: 108.: 60. SALGRADE : 5: 6.69: 0.: 152.: 22.: 30. DEPT : 4: 6.69: 0.: 124.: 18.: 31. 処理対象となった表の総数 : 3 ラウンドトリップ(回) : 136 出力バイト総数(kbytes) : 2.17 所要時間(秒) : 7.42 処理速度(kbytes/秒) : 0.29 正常終了しました。
startコマンドの画面でjava NamedPipeMulti を実行します。
C:\TEMP\java_test>java NamedPipeMulti *** Start: \\.\pipe\EMP.dat *** *** Start: \\.\pipe\DEPT.dat *** *** Start: \\.\pipe\SALGRADE.dat *** Waiting... "EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO" 7369,"SMITH","CLERK",7902,"19801217000000",800,,20 7499,"ALLEN","SALESMAN",7698,"19810220000000",1600,300,30 7521,"WARD","SALESMAN",7698,"19810222000000",1250,500,30 7566,"JONES","MANAGER",7839,"19810402000000",2975,,20 7654,"MARTIN","SALESMAN",7698,"19810928000000",1250,1400,30 7698,"BLAKE","MANAGER",7839,"19810501000000",2850,,30 7782,"CLARK","MANAGER",7839,"19810609000000",2450,,10 7839,"KING","PRESIDENT",,"19811117000000",5000,,10 7844,"TURNER","SALESMAN",7698,"19810908000000",1500,0,30 7900,"JAMES","CLERK",7698,"19811203000000",950,,30 7902,"FORD","ANALYST",7566,"19811203000000",3000,,20 7934,"MILLER","CLERK",7782,"19820123000000",1300,,10 *** End: \\.\pipe\EMP.dat *** "GRADE","LOSAL","HISAL" 1.E+00,7.E+02,1.2E+03 2.E+00,1.201E+03,1.4E+03 3.E+00,1.401E+03,2.E+03 "DEPTNO","DNAME","LOC" 4.E+00,2.001E+03,3.E+03 5.E+00,3.001E+03,9.999E+03 10,"ACCOUNTING","NEW YORK" *** End: \\.\pipe\SALGRADE.dat *** 20,"RESEARCH","DALLAS" 30,"SALES","CHICAGO" 40,"OPERATIONS","BOSTON" *** End: \\.\pipe\DEPT.dat *** Synchronyzed.
いかがでしたか?プログラムはうまく動いたでしょうか。シングルスレッド版のほうは、おおよそ予想通りの動きをしたかと思います。
それと比べると、マルチスレッド版のほうは毎回、CSVデータの表示される順序が変わるため同時実行されているという実感が沸きます。
サンプルインスタンス表の行数のオーダーでははっきりした差がありませんが、行数が数百万といったオーダーを超えるとマルチ・スレッド+名前付きパイプ接続の効果が現れてきます。
このチュートリアルを参考にOracle Database 上にある大量データを並列処理でスムーズに処理する java プログラム開発に皆さんもチャレンジしてみてはいかがでしょうか。
最後に、マルチスレッド・プロセスをプログラミングする上でのポイントをまとめます。