- PR -

DISTINCに関しての質問

投稿者投稿内容
ぬべたそ
ベテラン
会議室デビュー日: 2003/12/18
投稿数: 72
投稿日時: 2007-06-11 12:11
>めだかさん、かずくんさん
ご返信ありがとうございます。
こちらからの書き込みが遅くなり申し訳ありません。

テスト用のテーブルを以下のように作成し、実験してみました。
TEST_DATAという核になるデータを扱うテーブルに、TEST_GYOMU_Aという業務を扱うテーブルが履歴型でぶら下がるイメージです。
書き込みが長くなりますが、お許し下さい。
DBはOracle10gです。

コード:
CREATE TABLE TEST_DATA (
	DATA_ID			NUMBER(13) NOT NULL,
	DATA_CONTENT		VARCHAR2(255),
  	PRIMARY KEY(DATA_ID)
);

CREATE TABLE TEST_GYOMU_A (
	DATA_ID			NUMBER(13) NOT NULL,
	REVISION    	     NUMBER(3)  NOT NULL,
	REGIST_DATE		DATE,
	GYOMU_A_CONTENT	         VARCHAR2(255),
	PRIMARY KEY(DATA_ID, REVISION),
	FOREIGN KEY(DATA_ID) REFERENCES TEST_DATA
);



それぞれのテーブルに3万件のデータを作成し、以下のようなSQLを発行してみました。

コード:
SELECT
    TEST_DATA.DATA_ID,
    TEST_DATA.DATA_CONTENT,
    TEST_GYOMU_A.REVISION,
    TEST_GYOMU_A.REGIST_DATE,
    TEST_GYOMU_A.GYOMU_A_CONTENT
FROM TEST_DATA,TEST_GYOMU_A
WHERE 
TEST_DATA.DATA_ID=TEST_GYOMU_A.DATA_ID AND
REVISION = (SELECT
    MAX(B.REVISION)
FROM
    TEST_GYOMU_A B
WHERE
    B.DATA_ID=TEST_GYOMU_A.DATA_ID
) 



Explainの結果は以下のようになりました。
コード:
EXPLAIN実行結果>
 SELECT STATEMENT    Cost=1165
  2.1 FILTER    
    3.1 SORT GROUP BY   
      4.1 HASH JOIN    
        5.1 TABLE ACCESS FULL TEST_DATA TABLE 
        5.2 HASH JOIN    
          6.1 INDEX FAST FULL SCAN SYS_C0036658 INDEX (UNIQUE) 
          6.2 TABLE ACCESS FULL TEST_GYOMU_A TABLE 



次に業務Aと同様の構造のテーブル、業務Bを作成しました。
コード:
CREATE TABLE TEST_GYOMU_B (
	DATA_ID			        NUMBER(13) NOT NULL,
	REVISION    			NUMBER(3)  NOT NULL,
	REGIST_DATE		    	DATE,
	GYOMU_B_CONTENT	        VARCHAR2(255),
	PRIMARY KEY(DATA_ID, REVISION),
	FOREIGN KEY(DATA_ID) REFERENCES TEST_DATA
);



そして、このテーブルも結合するように以下のようなSQLを作成しExplainを実行したところ、
3つのテーブルを結合するSQL
コード:
SELECT
    TEST_DATA.DATA_ID,
    TEST_DATA.DATA_CONTENT,
    TEST_GYOMU_A.REVISION,
    TEST_GYOMU_A.REGIST_DATE,
    TEST_GYOMU_A.GYOMU_A_CONTENT,
    TEST_GYOMU_B.GYOMU_B_CONTENT
FROM TEST_DATA,TEST_GYOMU_A,TEST_GYOMU_B
WHERE 
TEST_DATA.DATA_ID=TEST_GYOMU_A.DATA_ID AND
TEST_DATA.DATA_ID=TEST_GYOMU_B.DATA_ID AND
TEST_GYOMU_A.REVISION = (SELECT
    MAX(B.REVISION)
FROM
    TEST_GYOMU_A B
WHERE
    B.DATA_ID=TEST_GYOMU_A.DATA_ID
)     
AND
TEST_GYOMU_B.REVISION = (SELECT
    MAX(C.REVISION)
FROM
    TEST_GYOMU_B C
WHERE
    C.DATA_ID=TEST_GYOMU_B.DATA_ID
)


Explain結果
コード:
EXPLAIN実行結果>
 SELECT STATEMENT    Cost=56583
  2.1 FILTER    
    3.1 SORT GROUP BY   
      4.1 FILTER    
        5.1 HASH JOIN    
          6.1 TABLE ACCESS FULL TEST_GYOMU_A TABLE 
          6.2 HASH JOIN    
            7.1 TABLE ACCESS FULL TEST_DATA TABLE 
            7.2 HASH JOIN    
              8.1 INDEX FAST FULL SCAN SYS_C0036662 INDEX (UNIQUE) 
              8.2 TABLE ACCESS FULL TEST_GYOMU_B TABLE 
        5.2 SORT AGGREGATE   
          6.1 FIRST ROW    
            7.1 INDEX RANGE SCAN (MIN/MAX) SYS_C0036658 INDEX (UNIQUE)


このように、COSTが大幅に増加してしまいました。

そこで、上記SQLに次の一行を追加してみました。
コード:
TEST_GYOMU_A.DATA_ID=TEST_GYOMU_B.DATA_ID


結合条件を冗長にしてみました。
Explainの結果は
コード:
EXPLAIN実行結果>
 SELECT STATEMENT    Cost=1548
  2.1 FILTER    
    3.1 SORT GROUP BY   
      4.1 FILTER    
        5.1 HASH JOIN    
          6.1 HASH JOIN    
            7.1 TABLE ACCESS FULL TEST_GYOMU_B TABLE 
            7.2 HASH JOIN    
              8.1 TABLE ACCESS FULL TEST_DATA TABLE 
              8.2 TABLE ACCESS FULL TEST_GYOMU_A TABLE 
          6.2 INDEX FAST FULL SCAN SYS_C0036662 INDEX (UNIQUE) 
        5.2 SORT AGGREGATE   
          6.1 FIRST ROW    
            7.1 INDEX RANGE SCAN (MIN/MAX) SYS_C0036658 INDEX (UNIQUE) 


のように、改善されたように見受けられます。

このような対策で問題無いでしょうか?
それとも他に見直さなければならない点などありました、ご教授下さい。
宜しくお願い致します。

スキルアップ/キャリアアップ(JOB@IT)