ファンクション索引を使用する際に統計情報に関する情報が必要になるので以下にコマンドを書いておきます。
統計情報の詳細についてはパフォーマンス・チューニング(初級編)を参照して下さい。
【表の統計情報を取得】オブジェクトの所有者で行なう |
---|
ANALYZE TABLE テーブル名 COMPUTE STATISTICS; |
【索引の統計情報を取得】オブジェクトの所有者で行なう |
---|
ANALYZE INDEX 索引名 COMPUTE STATISTICS; |
【表の統計情報を削除】オブジェクトの所有者で行なう |
---|
ANALYZE TABLE テーブル名 DELETE STATISTICS; |
【索引の統計情報を削除】オブジェクトの所有者で行なう |
---|
ANALYZE INDEX 索引名 DELETE STATISTICS; |
【表の統計情報を参照】DBAで行なう |
---|
SQL>COL TABLE_NAME FOR A15 SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, AVG_ROW_LEN, TO_CHAR(LAST_ANALYZED, 'MM/DD/YYYY HH24:MI:SS') FROM DBA_TABLES WHERE TABLE_NAME = 'テーブル名'; |
【索引の統計情報を参照】DBAで行なう |
---|
SQL>COL INDEX_NAME FOR A15 SQL> SELECT INDEX_NAME, NUM_ROWS, DISTINCT_KEYS "DISTINCT", LEAF_BLOCKS, CLUSTERING_FACTOR "CF", AVG_LEAF_BLOCKS_PER_KEY "ALFBPKEY" FROM DBA_INDEXES WHERE TABLE_NAME = 'テーブル名' ORDER BY INDEX_NAME; |
ファンクション索引を作成する事によるパフォーマンスの向上を試してみます。
なお、当機能は Oracle 8i Enterprise Edition または Oracle 9i Standard Edition以降 が必要です。
ファンクション索引は検索に使用する列に対する計算結果を事前に索引に登録しておき、検索時にその索引を使用するというものです。
ファンクション索引を使用する為には QUERY REWRITEシステム権限が必要になります。
また、該当の表に対して統計情報を取得しておく必要があります。
索引を作成しただけでは検索時に索引が使用されないので注意が必要です。
実際にファンクション索引を作ってみます。
今回使用するテーブル |
---|
SQL> DESC LTSTOCKDIC 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- KB_NCODE NOT NULL CHAR(7) →コード1 KB_SUBCD NOT NULL CHAR(5) →コード2 KB_FROM NOT NULL CHAR(8) KB_TO NOT NULL CHAR(8) KB_KRNAME1 VARCHAR2(30) →名前1 KB_KRNAME2 VARCHAR2(70) →名前2 データ件数は約 25,000件です。 名前1 +名前2 を検索の対象とします。 コード1+コード2も検索の対象とします。 |
ファンクション索引を作成する前に、索引作成前の実行計画と時間を示しておきます。
ファンクション索引を使用しない場合 |
---|
【実行計画】 SQL> SET AUTOTRACE TRACEONLY SQL> UPDATE LTLARGESTOCKO L SET ( L.KB_NCODE, L.KB_SUBCD ) = ( SELECT SD.KB_NCODE, SD.KB_SUBCD FROM LTSTOCKDIC SD WHERE ( SD.KB_NCODE || SD.KB_SUBCD) = ( SELECT MAX( D.KB_NCODE || D.KB_SUBCD ) CODE FROM LTSTOCKDIC D WHERE LTCMF000( L.KB_KBNAME ) = ( D.KB_KRNAME1 || D.KB_KRNAME2 ) ) ) WHERE L.CM_NCODE = '00000002' AND L.CM_YYYYMM = '200203'; 31行が更新されました。 Execution Plan ---------------------------------------------------------- 0 UPDATE STATEMENT Optimizer=CHOOSE (Cost=3 Card=33 Bytes=2838) 1 0 UPDATE OF 'LTLARGESTOCKO' 2 1 TABLE ACCESS (BY INDEX ROWID) OF 'LTLARGESTOCKO' (Cost=3 Card=33 Bytes=2838) 3 2 INDEX (RANGE SCAN) OF 'LTLARGESTOCKO_IXP' (UNIQUE) (Cost=2 Card=33) 4 0 INDEX (FULL SCAN) OF 'LTSTOCKDIC_IXP' (UNIQUE) (Cost=109 Card=241 Bytes=7712) 5 4 SORT (AGGREGATE) 6 5 TABLE ACCESS (FULL) OF 'LTSTOCKDIC' (Cost=65 Card=241 Bytes=16870) Statistics ---------------------------------------------------------- 0 recursive calls 186 db block gets 24154 consistent gets 0 physical reads 13856 redo size 858 bytes sent via SQL*Net to client 943 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 31 rows processed |
【実行時間】 SQL> SET TIMING ON SQL> UPDATE LTLARGESTOCKO L SET ( L.KB_NCODE, L.KB_SUBCD ) = ( SELECT SD.KB_NCODE, SD.KB_SUBCD FROM LTSTOCKDIC SD WHERE ( SD.KB_NCODE || SD.KB_SUBCD) = ( SELECT MAX( D.KB_NCODE || D.KB_SUBCD ) CODE FROM LTSTOCKDIC D WHERE LTCMF000( L.KB_KBNAME ) = ( D.KB_KRNAME1 || D.KB_KRNAME2 ) ) ) WHERE L.CM_NCODE = '00000002' AND L.CM_YYYYMM = '200203'; 31行が更新されました。 経過: 00:02:48.12 →2分48秒 |
ファンクション索引を作成します。
DBAで該当ユーザ(ファンクション索引を作成するユーザ)に QUERY REWRITEシステム権限を付与します。
今回は LT02 ユーザに権限を付与します。
SQL> CONNECT SYSTEM/MANAGER 接続されました。 SQL> GRANT QUERY REWRITE TO LT02; 権限付与が成功しました。 |
SQL> CONNECT LT02/LT02 接続されました。 SQL> CREATE INDEX DIC_TEST1 ON LTSTOCKDIC ( KB_KRNAME1 || KB_KRNAME2 ); 索引が作成されました。 SQL> CREATE INDEX DIC_TEST2 ON LTSTOCKDIC ( KB_NCODE || KB_SUBCD ); 索引が作成されました。 |
SQL> CONNECT LT02/LT02 接続されました。 SQL> ANALYZE TABLE LTSTOCKDIC COMPUTE STATISTICS; 表が分析されました。 |
SQL> CONNECT SYSTEM/MANAGER 接続されました。 SQL> COL TABLE_NAME FOR A15 SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, AVG_ROW_LEN, TO_CHAR(LAST_ANALYZED, 'MM/DD/YYYY HH24:MI:SS') FROM DBA_TABLES WHERE TABLE_NAME = 'LTSTOCKDIC'; TABLE_NAME NUM_ROWS BLOCKS AVG_ROW_LEN TO_CHAR(LAST_ANALYZ --------------- ---------- ---------- ----------- ------------------- LTSTOCKDIC 24045 670 198 03/04/2003 15:50:31 索引の統計情報を参照してみます。 SQL> COL INDEX_NAME FOR A15 SQL> SELECT INDEX_NAME, NUM_ROWS, DISTINCT_KEYS "DISTINCT", LEAF_BLOCKS, CLUSTERING_FACTOR "CF", AVG_LEAF_BLOCKS_PER_KEY "ALFBPKEY" FROM DBA_INDEXES WHERE TABLE_NAME = 'LTSTOCKDIC' ORDER BY INDEX_NAME; INDEX_NAME NUM_ROWS DISTINCT LEAF_BLOCKS CF ALFBPKEY --------------- ---------- ---------- ----------- ---------- ---------- DIC_INDX1 24045 4420 106 22138 1 DIC_INDX2 19236 4 82 546 20 DIC_TEST1 24045 22100 94 21958 1 DIC_TEST2 24045 24045 81 24021 1 LTSTOCKDIC_IXP 24045 24045 108 24021 1 |
索引作成後の実行計画と時間を示しておきます。
ファンクション索引を使用する場合 |
---|
【実行計画】 SQL> ALTER SESSION SET QUERY_REWRITE_ENABLED=TRUE; → 必要です! セッションが変更されました。 SQL> UPDATE LTLARGESTOCKO L SET ( L.KB_NCODE, L.KB_SUBCD ) = ( SELECT SD.KB_NCODE, SD.KB_SUBCD FROM LTSTOCKDIC SD WHERE ( SD.KB_NCODE || SD.KB_SUBCD) = ( SELECT MAX( D.KB_NCODE || D.KB_SUBCD ) CODE FROM LTSTOCKDIC D WHERE LTCMF000( L.KB_KBNAME ) = ( D.KB_KRNAME1 || D.KB_KRNAME2 ) ) ) WHERE L.CM_NCODE = '00000002' AND L.CM_YYYYMM = '200203'; 31行が更新されました。 Execution Plan ---------------------------------------------------------- 0 UPDATE STATEMENT Optimizer=CHOOSE (Cost=3 Card=33 Bytes=2838) 1 0 UPDATE OF 'LTLARGESTOCKO' 2 1 TABLE ACCESS (BY INDEX ROWID) OF 'LTLARGESTOCKO' (Cost=3 Card=33 Bytes=2838) 3 2 INDEX (RANGE SCAN) OF 'LTLARGESTOCKO_IXP' (UNIQUE) (Cost=2 Card=33) 4 0 TABLE ACCESS (BY INDEX ROWID) OF 'LTSTOCKDIC' (Cost=2 Card=1 Bytes=32) 5 4 INDEX (RANGE SCAN) OF 'DIC_TEST2' (NON-UNIQUE) (Cost=1 Card=1) 6 5 SORT (AGGREGATE) 7 6 TABLE ACCESS (BY INDEX ROWID) OF 'LTSTOCKDIC' (Cost=2 Card=2 Bytes=140) 8 7 INDEX (RANGE SCAN) OF 'DIC_TEST1' (NON-UNIQUE) (Cost=1 Card=2) Statistics ---------------------------------------------------------- 0 recursive calls 62 db block gets 73 consistent gets 0 physical reads 7700 redo size 859 bytes sent via SQL*Net to client 943 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 31 rows processed |
【実行時間】 SQL> SET TIMING ON SQL> UPDATE LTLARGESTOCKO L SET ( L.KB_NCODE, L.KB_SUBCD ) = ( SELECT SD.KB_NCODE, SD.KB_SUBCD FROM LTSTOCKDIC SD WHERE ( SD.KB_NCODE || SD.KB_SUBCD) = ( SELECT MAX( D.KB_NCODE || D.KB_SUBCD ) CODE FROM LTSTOCKDIC D WHERE LTCMF000( L.KB_KBNAME ) = ( D.KB_KRNAME1 || D.KB_KRNAME2 ) ) ) WHERE L.CM_NCODE = '00000002' AND L.CM_YYYYMM = '200203'; 31行が更新されました。 経過: 00:00:00.03 →0.03秒 |
まとめると以下の手順になります。
1. DBAで該当ユーザに QUERY REWRITシステム権限を付与する。
2. 該当ユーザにてファンクション索引を作成する。
3. 表の統計情報を取得する。
4. 該当セッションを変更する。
5. 検索を行う。
2003/03/04 担当:H.O