【回転】Oracle最適化の旅:leading,use_の使用nl,rownumチューニング例


注意:この文章は転帖で、学習記録だけです.テキストリンクhttp://blog.chinaunix.net/u/28618/showart_353192.html
1、leadingとuse_の使用nlはテーブルのクエリー順序を設定し、クエリー速度を速め、一般的に小さなテーブルを最初のテーブルに設定します.
/*+LEADING(TABLE)*/
指定するテーブルを接続順序の最初のテーブルとする.
/*+USE_NL(TABLE)*/
指定テーブルをネストする接続の行源に接続し、指定テーブルを内部テーブルとする.
原価計算方法:
小さなテーブル100行、大きなテーブル100000行を設定します.
両方のテーブルにインデックスがあります.
小さなテーブルを含めて大きなテーブルが外にある場合(駆動テーブル)、スキャン回数は:
100000+1000000*2(2はIO回数、1回のインデックス、1回のデータを表す)
大きなテーブルを含め、小さなテーブルが外にある場合(駆動テーブル)、スキャン回数は:
100+100*2.
両方のテーブルにインデックスはありません:
小さいテーブルを含めて大きいテーブルが外にある場合、スキャン回数は:
100000+100*100000
大きいテーブルを含めて、小さいテーブルが外にある場合、スキャン回数は:
100+100000*100
注意:テーブルにインデックスがあり、テーブルにインデックスがない場合、ORACLEはインデックスのないテーブルをドライバテーブルとします.両方のテーブルにインデックスがある場合は、外観が駆動テーブルになります.両方ともインデックスがない場合は、外観をドライバテーブルとして使用します.
2、indexを使用してインデックスを直接照合してデータを検索してクエリー速度を高める
/*+INDEX(TABLE INDEX_NAME)*/
テーブルに対してインデックスを選択するスキャン方法を示す.
3、あるテーブルに何らかの関係があるかどうかを判断するときはrownum=1を条件として速度を速め、条件を満たすには複数のローが必要な場合はrownum<=nを設定します.
たとえば、v_を取得します.count値判定が0より大きいか否か
equipmentテーブル数万本、controledpnsnrange数千本

select count(sc.pmnum)
  into v_count
  from equipment e,
       sal_controledpnsnrange sc
 where (sc.new_min_item_no <= e.itemnum)
   and (sc.new_max_item_no >= e.itemnum)
   and (sc.new_min_serial_no <= e.serialnum)
   and (sc.new_max_serial_no >= e.serialnum)
   and e.itemnum = a_item_no;

実行時間は約3分です.
コード修正後:

select /*+ leading(e) use_nl(sc) */
       count(sc.pmnum)
  into v_count
  from equipment e,
       sal_controledpnsnrange sc
 where (sc.new_min_item_no <= e.itemnum)
   and (sc.new_max_item_no >= e.itemnum)
   and (sc.new_min_serial_no <= e.serialnum)
   and (sc.new_max_serial_no >= e.serialnum)
   and e.itemnum = a_item_no;

実行時間は約45秒です.
コードの再変更後:

select /*+ leading(e) use_nl(sc) */
       count(sc.pmnum)
  into v_count
  from equipment e,
       sal_controledpnsnrange sc
 where (sc.new_min_item_no <= e.itemnum)
   and (sc.new_max_item_no >= e.itemnum)
   and (sc.new_min_serial_no <= e.serialnum)
   and (sc.new_max_serial_no >= e.serialnum)
   and e.itemnum = a_item_no
   and rownum = 1;

実行時間は約4秒です.