Oracle10g Cost Base Optimizerにまつわる検証 その9
<Oracle10g Cost Base Optimizerにまつわる検証 その9>
~DBMS_STATSの編~
ペンネーム:りん
先日、誕生日を迎えたりんです。こんにちは
年齢よりも体力年齢が年上ですが気にせず
さて、今週からまた検証生活をお送りしたいと思います。今年も当メルマガを
何卒よろしくお願い致します。
■おさらい
DBMS_STATSの編と題して、昨年から配信していますがお正月休みもあったので
おさらいしておきます。
・Monitoring属性
・Oracle Scheduler
・動的サンプリング
・DBMS_STATS
というCBO包囲網が形成されているということを書いてきました。
Oracle10gでは、RBOがサポートされなくなった為コストを算出する材料が自動
的に取得される…というわけです。
さらに、CBOの精度を高める為にDBMS_STATS.GATHER_SYSTEM_STATSについてを
Oracle 9i Release 2と比較して記載してきました。
■今回のお題
DBMS_STATS.GATHER_SYSTEM_STATSは、情報を取得して統計情報を取るわけです
がほとんどの場合、システムは時間帯によって負荷が変わってきます。
昼はスイスイ動いたのに、夜になると全然ダメ…
なんてことになったら「余計なことするなよー」と言われちゃいそうです。
なんとかならないものでしょうか?
というわけで、今回着目するのはオンライン時間帯とバッチ処理時間帯での運
用も視野に入れた、GATHER_SYSTEM_STATSについてを検証したいと思います。
■環境
Redhat Linux Advanced Server 2.1
Oracle Database 10g Enterprise Edition Release 10.1.0.2.0
■検証
では、CPUに高負荷をかけた場合に、どう変化するのかを確認したいと思いま
す。今までは、簡単なSELECT文でしたが、今回はSubqueryを使用して実行計画
が変化するかどうかを確認したいと思います。
100万件データをインサートしたテーブルを使ってSubQueryしちゃいましょう
SQL> create table dodekai_table ( id number, value number, data varchar2(200)); 表が作成されました。 SQL> begin 2 for cnt in 1..1000000 loop 3 insert into dodekai_table (id, value, data) 4 values ( cnt, cnt, 5 'データデータデータデータデータデータデータデータデータデータ データデータデータデータデータデータデータデータデータデータ'); 6 end loop; 7 commit; 8 end; 9 /
では、前回取得した「なにも負荷をかけていない状態」での統計情報を保持し
た状態でCPUを使う処理として大量のソート処理をSubQueryを使用して実行し
てみます。
SQL> alter session set events '10053 trace name context forever, level 1'; セッションが変更されました。 SQL> select out.id, out.value from ( select avg(VALUE) avg_value from dodekai_table ) sbq, 2 stats_test out where out.value <= sbq.avg_value order by id; 実行計画 ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=4981 Card=500 Bytes=10000) 1 0 SORT (ORDER BY) (Cost=4981 Card=500 Bytes=10000) 2 1 NESTED LOOPS (Cost=4980 Card=500 Bytes=10000) 3 2 VIEW (Cost=4962 Card=1 Bytes=13) 4 3 SORT (AGGREGATE) 5 4 TABLE ACCESS (FULL) OF 'DODEKAI_TABLE' (TABLE) (Cost=4962 Card=974847 Bytes=12673011) 6 2 TABLE ACCESS (FULL) OF 'STATS_TEST' (TABLE) (Cost=18 Card=500 Bytes=3500)
見てみると、100万件入っているDODEKAI_TABLEがフルスキャンされ、Sortされ
たViewが作成されています。
作成されたViewと、STATS_TESTテーブルとNested Loopでジョインされて、Sort
されたようですね…
では、このSQL文のトレースを見てみたいと思います。
なにやら、結合条件のコストが出力されていましたがSort処理のCPUのコスト
に着目したいと思います。
Sort Merge Joinの場合Total CPU sort cost: 10331355
Order byの場合Total CPU sort cost: 3980211
この結果から、Sort Merge Joinを採用せず、Order Byが採用されているようです。
では、CPUの負荷をあげてDBMS_STATS.GATHER_SYSTEM_STATSを実行してみます。
1時間CPUをガリガリ使って、統計情報を取得させてみた結果と負荷をかけるま
えと比較してみましょう
SYSSTATS_MAIN CPUSPEEDNW 566.641→566.641 SYSSTATS_MAIN IOSEEKTIM 10→10 SYSSTATS_MAIN IOTFRSPEED 4096→4096 SYSSTATS_MAIN SREADTIM 6.699→14.603 SYSSTATS_MAIN MREADTIM 0.385→92.778 SYSSTATS_MAIN CPUSPEED 564→230 SYSSTATS_MAIN MBRC 9→6 SYSSTATS_MAIN MAXTHR 27648→131072
となりました。
CPUSPEEDNW、IOSEEKTIM、IOTFRSPEEDに変更はありませんがその他の値は変更
されています。
IOもCPUも軒並み悪化しているようです。
これが、高負荷時の統計情報となります。
ではこの状態で同じSQL文を実行してみましょう
実行計画 ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=20127 Card=500 Bytes=10000) 1 0 SORT (ORDER BY) (Cost=20127 Card=500 Bytes=10000) 2 1 NESTED LOOPS (Cost=20126 Card=500 Bytes=10000) 3 2 VIEW (Cost=20060 Card=1 Bytes=13) 4 3 SORT (AGGREGATE) 5 4 TABLE ACCESS (FULL) OF 'DODEKAI_TABLE' (TABLE) (Cost=20060 Card=974847 Bytes=12673011) 6 2 TABLE ACCESS (FULL) OF 'STATS_TEST' (TABLE) (Cost=67 Card=500 Bytes=3500)
実行計画が変わるかな?!と思ったのですが実行計画に変化はありませんでした。
ただ、Costに注目してみると…
負荷をかける前後で、Costが変更されています。
CBOはとにかくCostの低いもの実行計画を選択するのであれば負荷状況によっ
ては、もしかしたら実行計画が変わる可能性もあるわけですよね。
■まとめ
・DBMS_STATS.GATHER_SYSTEM_STATSは取得時の負荷によって値が変わる
・実行計画を作成する際のコストも変更される。
→ということは、実行計画が変わる可能性もある…
というわけで、次回は統計情報の運用についてを検証したいと思います。
2005年も頑張るぞ!茅ヶ崎にて…