catch-img

Oracle SQLチューニング(第46回)「ROWNUMの理解と関連SQL性能問題の理解」(6/6回)

 今回のSQLチューニングは「 ROWNUMの理解と関連SQL性能問題の理解 」の最終回となります。
「 インラインビューにROWNUMを追加する時は注意しよう 」と題してお送りします。

 では、早速始めて行きましょう。

12.6  インラインビューにROWNUMを追加する時は注意しよう

 インラインビューにROWNUMを使用すると、Optimizerは実行計画を確立するときに、まずインラインビューのすべてのデータにROWNUMシーケンスを付与してから結合接続を行う必要があるため、ビュー外の条件がビュー内に侵入してSQLを解釈するQuery Transformation の種類の一つであるView Predicating機能を発揮できなくなります。

 この場合、パフォーマンスの問題が発生する可能性があるため注意してください。 以下は、ビュー内にROWNUMを追加した場合とそうでない場合の例です。

Script. テスト データ用

drop table rownum_t3 purge ;


< ROWNUM_T3 >

■ 生成要件

  • - ROWNUM_T2は既存テーブル使用
  • - ROWNUM_T3テーブルのデータは合計100,000ロー
  • - C1課C3はUnique下やC2は26種類値が存在する。

■ テーブル生成

create table rownum_t3
as
SELECT level AS c1, chr(65+mod(level,26)) AS c2, level+99999 AS c3
from DUAL

CONNECT BY level <= 100000 ;


■ 各カラムにインデックス生成および統計情報収集

CREATE INDEX rownum_t3_idx_01 ON rownum_t3 (c1) ;

EXEC dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'rownum_t3',cascade=>TRUE,estimate_percent=>100) ;

SQL[1]. インライン ビューにROWNUMを追加した時

var b1 varchar2(2)
var b2 number
exec :b1 := 'A';
exec :b2 := 102530;

SELECT t3.*, t2.*
  FROM ROWNUM_T2 t2,
       ( SELECT ROWNUM rnum, rownum_t3.*
           FROM ROWNUM_T3 ) t3
 WHERE t2.c1 = t3.c1
   AND t2.c2 = :b1
   AND t2.c3 = :b2 ;

--------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name             | Rows  |  Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                  |     5 |    225 |   315   (1)| 00:00:04 |
|*  1 |  HASH JOIN                    |                  |     5 |    225 |   315   (1)| 00:00:04 |
|   2 |   TABLE ACCESS BY INDEX ROWID | ROWNUM_T2        |     5 |     55 |   259   (0)| 00:00:04 |
|*  3 |    INDEX RANGE SCAN           | ROWNUM_T2_IDX_03 |   256 |        |     3   (0)| 00:00:01 |
|   4 |   VIEW                        |                  |   100K|   3320K|    54   (2)| 00:00:01 |
|   5 |    COUNT                      |                  |       |        |            |          |
|   6 |     TABLE ACCESS FULL         | ROWNUM_T3        |   100K|   1074K|    54   (2)| 00:00:01 |
--------------------------------------------------------------------------------------------------

SQL[2]. インライン ビュー外部にROWNUMを追加した時

var b1 varchar2(2)
var b2 number
exec :b1 := 'A';
exec :b2 := 102530;

SELECT rownum,
       t3.*, 
       t2.*
  FROM rownum_t2 t2,
       ( SELECT *
           FROM rownum_t3  ) t3
 WHERE t2.c1 = t3.c1
   AND t2.c2 = :b1
   AND t2.c3 = :b2 ;

---------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name             |  Rows | Bytes | Cost (%CPU)|  Time    |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                  |     5 |   110 |   269   (0)| 00:00:04 |
|   1 |  COUNT                         |                  |       |       |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID  | ROWNUM_T3        |     1 |    11 |     2   (0)| 00:00:01 |
|   3 |    NESTED LOOPS                |                  |     5 |   110 |   269   (0)| 00:00:04 |
|   4 |     TABLE ACCESS BY INDEX ROWID| ROWNUM_T2        |     5 |    55 |   259   (0)| 00:00:04 |
|*  5 |      INDEX RANGE SCAN          | ROWNUM_T2_IDX_03 |   256 |       |     3   (0)| 00:00:01 |
|*  6 |     INDEX RANGE SCAN           | ROWNUM_T3_IDX_01 |     1 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------

 SQL[1],SQL[2]は同じデータを抽出するがROWNUMの実行位置により性能に大きい差を見せています。

 従って、単純にインラインビューの結果セットに順番を付与するために使われるROWNUMを使う場合には、

 ROWNUMの使用位置を慎重に考慮しなければなりません。注意しましょう。

● まとめ

 「 ROWNUMの理解と関連SQL性能問題の理解 」について、全6回のシリーズでお届けしてきました。どうでしたか?

 ROWNUMとは、ユーザーの利便性とパフォーマンス向上を目的としてOracleが提供する仮想列のことです。
 作成者の意図を正確に把握して使用することで、パフォーマンスの向上に繋げることができます。
 しかしそれとは逆に、意図を正確に把握せずに使用すると、パフォーマンスに悪影響を及ぼすことがあります。
 更には、SQLを構成している各要素が「SQL内でどのような役割を果たしているか?」を正確に理解して使用できれば、その効果を最大化することができるはずです。
 そのため、ROWNUMがSQLで実行する役割を理解し、他の条件(Where節、Order By節など)と一緒に使用されるときにどのような順序で解釈されるのか?を先行して理解しなければ、SQLを効率的に作成することができません。

 今回のテーマで説明した内容を踏まえてROWNUMについてよく理解し、効率的に使用できることを願っています。

 SQLチューニングブログ(第46回) 終



 今回の Oracle SQLチューニングブログ はいかがでしたか?
 次回からは「画面PAGINATION処理する時これは守ろう」を7回シリーズでお送りします。



CONTACT

他社に頼らず自社でデータベースを監視・運用をしませんか?
MaxGaugeがサポートします

お役立ち資料は
こちらから

不明点がある方は、
こちらからお問い合わせください

お電話でのお問い合わせはこちら

平日 10時~18時

人気記事ランキング

タグ一覧