クラスタ索引を使ってみた
クラスタ索引とは、簡単に言うと頻繁に結合するテーブル同士の結合条件Columnを一カ所に集中させて
ディスクのランダムアクセスを減らそう(シーケンシャルアクセスにする)っていうものかな
詳細は下記へ
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19207-02/data_acc.htm#801641
ともかく一カ所にまとまってたら早くなるってイメージで良いです
以前触ったことはあったけどあんま使い方覚えてないので再度挑戦
まずはクラスタ作成
CREATE CLUSTER MST_TRAN ( MST_ID NUMBER )
次にクラスタを使用するテーブルを作成
MSTとTRANテーブルをこんな感じで
CREATE TABLE MST ( MST_ID NUMBER NOT NULL, NAME VARCHAR2(20), CONSTRAINT PK_MST_ID PRIMARY KEY (MST_ID) USING INDEX ) CLUSTER MST_TRAN (MST_ID)
CREATE TABLE TRAN ( TRAN_ID NUMBER NOT NULL, NAME VARCHAR2(10), MST_ID NUMBER, CONSTRAINT PK_TRAN_ID PRIMARY KEY (TRAN_ID) USING INDEX ) CLUSTER MST_TRAN (MST_ID)
もう一つ、同じテーブル構成でクラスタを使用しないMST2,TRAN2を作成
A. MST,TRAN = ClusterIndex(MST_ID)
B. MST2,TRAN = クラスタなしFKのみ
んでテストデータとして
MST,MST2 = 1,000rec
TRAN,TRAN2 = 100,000rec
A.
SELECT M.* ,T.* FROM MST M INNER JOIN TRAN T ON T.MST_ID = M.MST_ID
B.
SELECT M.* ,T.* FROM MST2 M INNER JOIN TRAN2 T ON T.MST_ID = M.MST_ID
結果
A.
- 実行計画
- Cost:2
- Byte:58
- Join:NESTED LOOPS
- AutoTrace
- consistent gets:13004
B.
- 実行計画
- Cost:111
- Byte:6103862
- Join:HASH JOIN
- AutoTrace
- consistent gets:10349
とりあえず実行計画だけでみると圧倒的にクラスタ索引が強いが
どうも実行計画を見ると勝手に最適化されているようなので
NestedLoop と HashJoin で別々に実行計画とってみることにする。
ヒント句で NestedLoop
A.
SELECT /*+USE_NL(M,T)*/ M.* ,T.* FROM MST M INNER JOIN TRAN T ON T.MST_ID = M.MST_ID
B.
SELECT /*+USE_NL(M,T)*/ M.* ,T.* FROM MST2 M INNER JOIN TRAN2 T ON T.MST_ID = M.MST_ID
結果
A.
- 実行計画
- Cost:2
- Byte:58
- join:NESTED LOOPS
- AutoTrace
- consistent gets:13004
B.
- 実行計画
- Cost:1067
- Byte:6103862
- Join:NESTED LOOPS
- AutoTrace
- consistent gets:10349
ヒント句で HashJoin
A.
SELECT /*+USE_HASH(M,T)*/ M.* ,T.* FROM MST M INNER JOIN TRAN T ON T.MST_ID = M.MST_ID
B.
SELECT /*+USE_HASH(M,T)*/ M.* ,T.* FROM MST2 M INNER JOIN TRAN2 T ON T.MST_ID = M.MST_ID
A.
- 実行計画
- Cost:5
- Byte:58
- join:HASH JOIN
- AutoTrace
- consistent gets:11910
B.
- 実行計画
- Cost:111
- Byte:6103862
- HASH:JOIN
- AutoTrace
- consistent gets:10349
SortMergeもためしてみた
A.
SELECT /*+USE_MERGE(m,t)*/ M.* ,T.* FROM MST M INNER JOIN TRAN T ON T.MST_ID = M.MST_ID
B.
SELECT /*+USE_MERGE(m,t)*/ M.* ,T.* FROM MST2 M INNER JOIN TRAN2 T ON T.MST_ID = M.MST_ID
A.
- 実行計画
- Cost:3
- Byte:58
- Join:SORT MERGE
- AutoTrace
- consistent gets:4006
B.
- 実行計画
- Cost:1063
- Byte:6103862
- Join:SORT MERGE
- AutoTrace
- consistent gets:457
上記の事を試して気づいたのだがクラスタ索引はHashJoinでは使われない
気になってマニュアル読んでたら別途ハッシュクラスタってのがあるみたい
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19224-02/hash.htm#14273
ちなみにこの件数では体感はどちらでも変わりませんでした。
ただ以前試した際には、クラスタなしは件数が増加するに従ってパフォーマンスの低下が激しかったけど
クラスタでは件数の増加してもそこまでパフォーマンスが落ちなかった記憶があるので
1000万とか1億とかのレコードをガシガシJoinするのであれば有効だと思いますよ