データのロードは外部表を使うのが一番簡単で早い。
また 6coreのCPUなのでデータを6つに分けることと、データを圧縮して速度向上を図ってみました。SSDだと圧縮効果が薄れると思うが、HDDを使う場合は圧縮することによりかなり時間が短くなります。
$ dbgen -f -C6 -S1 -s32 & $ dbgen -f -C6 -S2 -s32 & ... $ dbgen -f -C6 -S6 -s32 & $ gzip *.tbl
以下が、データロードするSQL文。lineitemだけを書いているが、これを他の7つのテーブルにも行う。(元になるSQL文は Create Your Own Oracle TPC-H Playground on Linux の情報を大いに参考にして作成しました。)
CREATE OR REPLACE DIRECTORY tpch_dir AS '/home/oracle/....' / CREATE OR REPLACE DIRECTORY zcat_dir AS '/bin' / CREATE TABLE lineitem_ext ( l_orderkey NUMBER(10) , l_partkey NUMBER(10) , l_suppkey NUMBER(10) , l_linenumber NUMBER(38) , l_quantity NUMBER , l_extendedprice NUMBER , l_discount NUMBER , l_tax NUMBER , l_returnflag CHAR(1) , l_linestatus CHAR(1) , l_shipdate VARCHAR2(10) , l_commitdate VARCHAR2(10) , l_receiptdate VARCHAR2(10) , l_shipinstruct VARCHAR2(25) , l_shipmode VARCHAR2(10) , l_comment VARCHAR2(44) ) ORGANIZATION EXTERNAL ( TYPE oracle_loader DEFAULT DIRECTORY tpch_dir ACCESS PARAMETERS ( RECORDS DELIMITED BY NEWLINE PREPROCESSOR zcat_dir:'zcat' BADFILE 'bad_%a_%p.bad' LOGFILE 'log_%a_%p.log' FIELDS TERMINATED BY '|' MISSING FIELD VALUES ARE NULL ) LOCATION ( 'lineitem.tbl.1.gz' , 'lineitem.tbl.2.gz' , 'lineitem.tbl.3.gz' , 'lineitem.tbl.4.gz' , 'lineitem.tbl.5.gz' , 'lineitem.tbl.6.gz' ) ) PARALLEL 6 REJECT LIMIT 0 NOMONITORING / CREATE TABLE lineitem ( l_orderkey NUMBER(10) NOT NULL , l_partkey NUMBER(10) NOT NULL , l_suppkey NUMBER(10) NOT NULL , l_linenumber INTEGER NOT NULL , l_quantity NUMBER NOT NULL , l_extendedprice NUMBER NOT NULL , l_discount NUMBER NOT NULL , l_tax NUMBER NOT NULL , l_returnflag CHAR(1) NOT NULL , l_linestatus CHAR(1) NOT NULL , l_shipdate DATE NOT NULL , l_commitdate DATE NOT NULL , l_receiptdate DATE NOT NULL , l_shipinstruct VARCHAR2(25) NOT NULL , l_shipmode VARCHAR2(10) NOT NULL , l_comment VARCHAR2(44) NOT NULL ) PCTFREE 1 PCTUSED 99 PARALLEL 6 / INSERT /*+append*/ INTO lineitem SELECT l_orderkey , l_partkey , l_suppkey , l_linenumber , l_quantity , l_extendedprice , l_discount , l_tax , l_returnflag , l_linestatus , to_date(l_shipdate, 'yyyy-mm-dd') , to_date(l_commitdate, 'yyyy-mm-dd') , to_date(l_receiptdate, 'yyyy-mm-dd') , l_shipinstruct , l_shipmode , l_comment FROM lineitem_ext / BEGIN dbms_stats.gather_table_stats(ownname => 'TPCH_&TESTID.', tabname => 'LINEITEM', degree => 6, cascade => TRUE) ; END; /
ALTER TABLESPACE tpch_&TESTID. READ ONLY;
あと、もう1つ大人な事情があった!
今回はインデックスを利用できない時の処理速度を測定したかったので、TPC-Hを正確に測定する際は必ず作成しなければいけない primary key, foreign key を全て作成しないようにしました。
なので全てのデータに対して FULL Table Scanとなります。例えば lineitemであれば、次のようなインデックスを作成する必要があるのです。
-- PK Constraints CREATE UNIQUE INDEX lineitem_pk ON lineitem(l_linenumber, l_orderkey) PARALLEL 2 / ALTER TABLE lineitem ADD CONSTRAINT lineitem_pk PRIMARY KEY(l_linenumber, l_orderkey) USING INDEX lineitem_pk / -- FK Constraints ALTER TABLE lineitem ADD CONSTRAINT lineitem_partsupp_fk FOREIGN KEY(l_partkey, l_suppkey) REFERENCES partsupp(ps_partkey, ps_suppkey) NOT DEFERRABLE / ALTER TABLE lineitem ADD CONSTRAINT lineitem_orders_fk FOREIGN KEY (l_orderkey) REFERENCES orders(o_orderkey) NOT DEFERRABLE /
まあ、正確なTPC-Hの測定にはなりませんが、余計なインデックスは邪魔なので良しとします。
で、前回説明したとおり qgenで作成したSQL文 22個を
デフォルトの blocksize=8k で作成したデータで、とりあえず実行してみた。
そしたら 3436秒 = 57分16秒 だった。
果たしてこれは速いのか。
次回は TPC-Hで使う QphHの計算方法について触れ、
上記の処理時間が、どれ位なものなのかを考えてみることにしよう。
※ 2011/4/5 追記: TPC-H用リポジトリを作成するSQL文の元ネタの場所を追記しました。
create directory zcat_dir as '/bin'
返信削除これは何をやっているのですか?
今回ロードするデータは圧縮しているので、
返信削除外部表の ORACLE_LOADERパラメータに次の指定をしてます。
REPROCESSOR zcat_dir:'zcat'
ここは '/bin/zcat'とは書けず、ディレクトリ・オブジェクトにする必要があったはず。多分セキュリティ上の理由。
なので create directory してます。