門外不出のOracle現場ワザ

日本オラクル株式会社 コンサルティング統括本部テクノロジーコンサルティング本部 小田 圭二(おだ けいじ)

第2章 万全の予防とテストで致命的トラブルを回避するOracle管理 転ばぬ先の杖

日本オラクル株式会社 コンサルティング統括本部テクノロジーコンサルティング本部 小田 圭二(おだ けいじ)

目次

Part2 パフォーマンステストにおける正しい環境作りと統計情報の分析

パフォーマンステストの一番の目的とは、システムがレスポンス要件やスループット要件を満たしているかを、事前に確認することです。もし、テストによってパフォーマンスに問題が発見された場合は、チューニングと再テストを要件が満たされるまで繰り返し、最終的には、本番稼動を迎える前にパフォーマンス上の不安要素をすべて取り除きます。しかし、そこまで手を尽くしても、カットオーバー直後に予期せぬパフォーマンス劣化が発生することも多いのではないでしょうか。 本パートでは、テストを行なったにもかかわらず、本番稼動後にパフォーマンス劣化を招いてしまった実際の事例を解説しながら、「トラブルを未然に防ぐパフォーマンステスト」について考えます。

レスポンスタイムやスループットがすべてじゃない!

筆者は、前述したカットオーバー直後に発生したパフォーマンス劣化の原因の多くは、パフォーマンステストにおいてレスポンスタイムやスループットの結果だけが注目されすぎて、パフォーマンステストの本質を見失っていることにあると考えています。次のようなケースを考えてみてください。

良すぎるキャッシュヒット率に注意

一般に、キャッシュヒット率は100%に近ければ近いほど良いと言われています。当然、ディスクアクセスよりもメモリ(Oracleのバッファキャッシュ)アクセスのほうが短時間でデータを取得できるので、本番データベースにはヒット率を100%に近づけるためのさまざまなチューニングを施します。しかし、パフォーマンステストにおいては、高いキャッシュヒット率を手放しで喜んではいけません。

筆者が以前携わったプロジェクトで、テスト結果の値がレスポンスやスループットの要件を大きくクリアし、STATSPACKのレポートを見てもOracleのバッファキャッシュに対するヒット率が99.99%という、一般的には理想的とされる値が計測されたことがありました。しかし、この99.99%という値は、アプリケーションの処理内容から考えるとあまりに“良すぎる”結果でした。そのため、テストで使用した負荷シミュレータのロジックを精査したところ、テストデータのほんの一部にしかアクセスしない作りになっていることが判明しました。

具体的に説明すると、あらかじめ検索対象データを記載した複数のファイルを読み込んでSQL文を生成する仕組みのはずが、用意した複数のファイルのうち1つだけを繰り返し読み込むようなロジックとなっていたのです(図1)。

図1 良すぎるキャッシュヒット率の原因 図1 良すぎるキャッシュヒット率の原因

そのため、検索対象となったデータのサイズは、全データを合わせてもOracleのバッファキャッシュサイズよりも小さくなってしまい、一度キャッシュ上に載ってしまうと、その後はキャッシュアウトされることはありません。その結果、負荷シミュレータのSQLは検索対象のデータを必ずバッファキャッシュから読み込むことができました。こうして、良すぎるキャッシュヒット率が計測されたのです。

後日、作り直した負荷シミュレータで再度テストしたところ、システムは要件をクリアできず、テスト中のキャッシュヒット率も大きく落ち込みました。案の定、ディスクからのデータの読み込みが増えたことが、性能に影響を与えたのです。

このとき、もしレスポンスタイムやスループットにのみ注目してパフォーマンステストそのものの不自然さに気づかなかったら、もし再テストを行なわずに本番稼動を迎えていたら……、きっと後に大きなトラブルとなっていたことでしょう。

キャッシュの状態をイメージしよう

こうした問題は、何も負荷シミュレータのロジックの出来/不出来によってのみ引き起こされるわけではありません。テストの実施の手順、準備したテストデータのサイズ、用意したテスト環境のスペックなど、さまざまな要因によって起こり得ます。 パフォーマンステストにおいてOracleのバッファキャッシュが適正に使用されるようにするにはどうすれば良いのでしょうか? その第一歩は、パフォーマンステストにおいて、DBAが本番システムにおけるデータベースのバッファキャッシュの使われ方をできるだけ正確にイメージすることだと筆者は考えます。

COLUMNアドバイス!ランダム関数

検索対象をランダム関数によって生成するケースは多く見られますが、そのランダム関数にまつわる負荷シミュレータの失敗談をお話ししましょう。

処理実行時の時間を利用して乱数を生成する負荷シミュレータを使用したときの話です。負荷シミュレータを複数起動して多重に処理を投入した際、同時に実行した処理では同じ値の乱数が発生するために、同じデータに処理が集中し、その競合が激しいオーバーヘッドを引き起こして、パフォーマンスを劣化させてしまいました。

また別のケースでは、ランダム関数が生成する値の範囲が格納されたデータの範囲よりも狭かった(例えば、1~1000の値をとるデータに対して、生成される乱数は1~100の範囲だった)ため、キャッシュヒット率が実際よりも良い値となってしまったこともあります。 本編のファイルの話やランダム関数の話は、特定のプロジェクトの話ではありません。一般に見かけるものなので、皆さんもご注意ください。

正確なイメージを持つためには、アプリケーションからデータベースに対してどのような問い合わせが、どのような頻度で行なわれるのかを知り、それをもとに本番システムでのデータへのアクセスパターンを頭の中でシミュレーションすることが重要です。そして、イメージどおりにバッファキャッシュの状態を保つようにパフォーマンステストを実施します。 例えば、オンライン時間帯では稀にしかアクセスしないテーブルに対して検索を行なう夜間バッチ処理のパフォーマンステストを行なう場合を考えてみましょう。この場合、バッチ開始時に検索対象データがキャッシュに載っているはずはありません。したがって、適正なキャッシュの状態を得るために、パフォーマンステストの前にデータベースやOS、ストレージのキャッシュをクリアした状態にします。複数回テストを実施する場合は、その都度キャッシュをクリアしなければなりません。

逆に、オンライン時間帯のレスポンスタイムやスループットを計測する場合を考えてみましょう。オンライン時間帯中に頻繁に参照されるマスターテーブルなどは、常にキャッシュ上に存在しメモリアクセスされるはずです。正しくテストを行なうには、テストアプリケーションを空回しし、本番稼動時のキャッシュの状態を再現してから測定を開始するべきです(オンラインのサービス開始直後のレスポンスタイムを測定する必要がある場合はこの限りではありません)。これらの考え方は、データベースだけでなくOSのキャッシュやストレージのキャッシュについても同様です。 データの量とメモリサイズの関係についても注意を払ってください。例えば、本番環境と同容量のテストデータを用意できなかった場合や、スモールスケールのテスト環境しか用意できずバッファキャッシュのサイズが本番環境よりも小さい場合です。 前者のケースでは本来キャッシュに載り切らないはずのデータがすべてキャッシュに載ってしまい、性能が良すぎる結果となる可能性があります。その場合、本番稼動後にパフォーマンス問題が発生し、DBAはディスクI/Oの分散やSQLチューニングなどの作業に奔走することになるでしょう。 後者のケースでは、逆にメモリからアクセスできたはずのデータをディスクからアクセスするために、テストで本来のパフォーマンスを確認できません。これでは、ディスクI/Oの影に隠れた本当のボトルネックを見逃してしまい、見当外れなチューニングに時間を費やすことになります。こうした問題を防ぐために、データサイズはキャッシュサイズに比例して調整してください。

COLUMNアドバイス!Oracleのキャッシュヒット率とは?

Oracleのキャッシュヒット率とは、データブロックを使用する際に、該当ブロックをメモリ上、つまりSGA内のデータベースバッファキャッシュ上から見つけることができた割合です。キャッシュヒット率100%とは、必要なデータブロックがすべてメモリ上から発見できたことを意味します。 Oracleのキャッシュヒット率は、STATSPACKレポートの“Instance Efficiency Percentages”に記載された“Buffer Hit”から分かります。この値は、V$SYSSTATビューで検索できるシステム統計情報と次の式によって求められています。


  
(1 -('
                                   physical reads' 
- '
                                   physical reads direct'
- '
                                   physical reads direct(lob)')
/ '
                                   session logical reads')* 100
 
 

※下線の情報をV$SYSSTATビューから得ることができます

STATSPACKを導入していない場合でも、V$SYSSTATビューと上の式からキャッシュヒット率は計算できます。なお、V$SYSSTATビューから得られる統計情報は、インスタンスを起動してからの累積値ですので、一定の期間のキャッシュヒット率を得るには、ある時点と別のある時点の統計情報値の差分を使って計算する必要があります。

最後に、負荷シミュレータ自体の問題です。負荷シミュレータが投入するトランザクションは、本番とテストとの環境相違がない限り、本番システムのアプリケーションが投入するトランザクションをできる限り正確にシミュレートしていなければなりません。これは、本番と同じSQLがデータベースに流れてさえいれば良いというものではありません。SQLの投入量(実行回数)や投入配分も本番業務を意識してください。投入量や投入配分が異なれば、データベースのI/O特性が本番と異なるためにキャッシュの状態に影響が出るばかりか、データベース内部のアクティビティも本番と異なるためにボトルネックの箇所などが変わってしまう可能性があります。

過剰キャッシュヒットを見破るには?

万全を期したはずのパフォーマンステストでも、キャッシュが正しく使われていないなどの不備があるかもしれません。では、それらをテスト後に発見する良い方法はあるのでしょうか? 残念ながら、OSの情報やSTATSPACKなどのデータから不正にキャッシュヒット率が高い(低い)事象を簡単に見破る完全確実な方法はありません。ただ、いくつかのケースで、怪しい兆候を見逃さないようにすることは可能です。 例えば、STATSPACKの「InstanceActivity」にレポートされる「physical reads」と「physical writes」に注目します(LIST1)。

LIST1 STATSPACKレポートの「Instance Activity」情報

LIST1 STATSPACKレポートの「Instance Activity」情報

physical readsおよびphysical writesとデータベースのブロックサイズの積は、データベースの行なった物理I/Oのサイズを表わします。この値がバッファキャッシュのサイズと比較して小さすぎる場合、用意したテストデータの量が少なすぎないか、もしくは負荷シミュレータが検索対象とするデータの範囲が狭すぎないかを疑ってください。 もう少し詳細に物理I/Oを見てみましょう。 「File IO Stats」にレポートされるデータファイルごとの物理I/Oに注目します(LIST2)。File IO Statsの各データファイルの物理I/Oの値を比較して、一部のデータファイルに物理I/Oが偏っている場合には、負荷シミュレータが一部のデータにしかアクセスしていない可能性があります。

LIST2 STATSPACKレポートの「File IO Stats」情報

LIST2 STATSPACKレポートの「File IO Stats」情報

また、各SQL文の詳細情報である「SQLordered by Gets」「SQL ordered byReads」「SQL ordered by Executions」などからも、負荷シミュレータのアクセス状況をイメージすることができます(LIST3)。これらのレポートに記載される「Gets per Exec」「Reads per Exec」「Rows per Exec」は、それぞれ1実行あたりの使用ブロック数、物理読み込みブロック数、取得行数を示します。これらの値が、ゼロもしくはゼロに近い値になっていたり、本番システムにおける問い合わせの処理パターンと合致しないような値になっていたりするかどうかが、試験結果の信憑性を計る1つの指標になります。 いずれにしても、本番システムのアプリケーションをイメージしながらSTATSPACKレポートを見る習慣をつけ、記録された値やSQL文が適正かどうかを判断する目を養う必要があります。

以上、キャッシュヒット率が良すぎる例を挙げて、パフォーマンステストを正しく実施するための考え方について解説してきました。ここで述べたことは、キャッシュヒット率に特化した問題として取り上げたわけではありません。あらゆる状況に関しても同様に当てはまることとして、参考にしてください。

LIST3 STATSPACKレポートのSQL詳細情報

LIST3 STATSPACKレポートのSQL詳細情報

COLUMNアドバイス:理想のデータと負荷

パフォーマンステストにおける理想のデータと負荷とは、本番環境と同じデータが格納されたデータベースに対して、本番と同等のトランザクションをデータベースに投入することです。データに関しては、可能であれば本番データをそのまま使用することです。顧客情報などの情報漏洩の危険を犯せないデータに関しては、一部を擬似データに置き換えて使用しても良いでしょう。負荷に関しては、実際に人間を集めて本番さながらに処理を実行してテストを行なったり、負荷ツールを使用します。システムのリプレースに伴うパフォーマンステストの場合は、現行システムのトランザクションログを利用して、実際に本番環境で流れたトランザクションを負荷シミュレータ上で再 現する方法も、システムの重要度に応じて検討すべきです。 どこまで本番に近づけるべきかは、リスクとコストのバランスによるために一概に言えませんが、主要な処理はシミュレートしていただければと思います。

▲ ページTOPに戻る

転ばぬ先のデータ収集

ここまでに、テスト結果を見る際にレスポンスタイムやスループットの値だけに目を奪われないようにすることが非常に重要なことを、再認識していただいたと思います。しかし、現場、特に業務側の担当者は、性能をレスポンスタイムとスループットの値だけで測ってしまう傾向があります。よしんば、ほかの性能情報を見たとしても、OSのCPU使用率やメモリ使用率に留まるケースがほとんどです。

しかし、これだけの情報では、データベースがテスト中にどのような挙動をしていたのか、データベースは効率良く作業をしていたのか、何よりパフォーマンステストが適正に行なわれていたのかを確認することが困難です。そのため、たとえテスト時点では要件を満たしていたとしても、性能劣化を引き起こしそうな兆候が潜んでいるような場合に、それを見落としてしまうことになります。 こうした情報不足に起因する兆候の見落としを招かないために、筆者がコンサルティングを行なうプロジェクトでは、パフォーマンステスト時には最低限、表1の情報を取得するようにお願いしています。

表1 パフォーマンステスト時に最低限取得すべき情報

表1 パフォーマンステスト時に最低限取得すべき情報

パフォーマンステスト時にこれらの情報が取得されていれば、データベースの性能解析時に困ることはほとんどありません。また、原因不明の性能劣化が発生してベンダのサポートセンターに問い合わせるときにも、これらの情報が役立つ場合があります。DBAの“転ばぬ先の杖”として、ぜひ、表1に示した情報を収集するようにしてください。 以降、表1に挙げた情報の取得方法および取得意図について解説します。

STATSPACK(レベル7)

先ほどから利用を促しているSTATSPACKは、Oracle8i(リリース8.1.6)から使用可能になったパフォーマンス診断ツールです。STATSPACKは従来のBSTAT/ESTATの後継であり、無償のPL/SQLスクリプトとして提供されるため、誰でもどんな環境でも使えます。

STATSPACKでは、OracleのCPUの使用時間やI/O情報、リソースを大量消費するSQL文の情報を収集することができます。筆者がパフォーマンステストにおいて推奨しているSTATSPACKのレベル7 注1では、それらの情報に加えて、使用頻度の高いセグメント(ほぼテーブルに相当)ごとに統計情報も収集できます(表2)。パフォーマンステスト中のデータベースのアクティビティは、STATSPACKを解析することでほぼ把握できます。

STATSPACKで情報を取得する場合は、図2のように、テスト開始直前と終了直後に「スナップショット」を取得します。また、テストの最中にも定期的に(システムの負荷にもよりますが、5分~30分おき)スナップショットを取得します。スナップショット取得時には、自動的にIDが採番されるので、テスト終了後に2つのスナップショットID間の性能情報をレポート出力し、解析が実行されます。

注1:STATSPACKでは、収集する統計情報の粒度を“レベル”によって調整できます。デフォルトのスナップショットレベルは5に設定されています。レベルの設定方法は、製品マニュアル『Oracle9i データベース・パフォーマンス・チューニング・ガイド』を参照してください。

図2 STATSPACKのスナップショットとレポートの出力

図2 STATSPACKのスナップショットとレポートの出力

注意!

STATSPACKレベル7において「セグメント統計」を取得するためには、初期化パラメータ「STATISITCS_LEVEL」を“TYPICALあるいはALL”に設定する必要があります。なお、セグメント統計の取得機能やSTATISITCS_LEVEL初期化パラメータはOracle9iリリース 2(9.2.0)の新機能ですので、Oracle8i、Oracle9iリリース 1では設定できません。

OS情報

STATSPACKを使い、Oracleの性能情報を解析しただけで満足してはいけません。システムは図3のように、さまざまなレイヤで構成されています。アプリケーション(クライアント)が処理要求を出してから結果を受け取るまでには、これらすべてのレイヤが相互に連携しながら処理を進めています。ここで重要なのは、クライアントもアプリケーションサーバーもOS上で動作しており、OracleもミドルウェアといえどもOS上で動作する1アプリケーションであるという点です。つまり、Oracleをはじめ、システム全体はOSリソースの状況に非常に大きな影響を受けるのです。

図3 システムを構成するさまざまなレイヤ

図3 システムを構成するさまざまなレイヤ

例えば、CPUリソースが枯渇したりディスクI/Oが遅延したりしていても、STATSPACKレポート上ではOracleの待ち(待機イベント)が増加します。そのため、パフォーマンス劣化の原因があたかもOracleにあるように見える場合が多々あります。ですから、性能劣化の原因がOSリソースにあるのか、ストレージのI/Oパフォーマンスにあるのかなどを見破るためには、Oracleの性能情報(STATSPACKレポート)だけでなく、OSの性能情報も収集し、両者を突き合わせてシステムの負荷状況をとらえることが重要です。 OSに関しては、次の情報を5秒~30秒程度の間隔で取得してください 注2。

●CPU/メモリの情報(取得ツール:sar、vmstatなど)

  • CPU使用率

  • CPUのRunキュー長

  • スワッピング状況

  • カーネルメモリ使用状況

  • ユーザーメモリ使用状況

●DISK I/O情報(取得ツール:iostat、vxstatなど)

  • ディスクI/O量

  • ディスクビジー率

  • 平均サービス時間

  • 平均待ち時間

これら以外にも、ネットワーク上やストレージ上、アプリケーションサーバー上で取得するべき性能情報もありますが、本特集ではOracleだけに話を集中するため、説明は割愛します。また、残念ながら、これらの情報とSTATSPACKを組み合わせたパフォーマンス分析手法やノウハウの詳細については、ここでは解説できません。市販の書籍、もしくは本誌2004年7月号の特集2にある解説が参考になりますので、そちらを参照していただくと良いでしょう。

注2:OS情報を取得するコマンドは、OSによって異なります。詳細は各OSのマニュアルを参照してください。

COLUMNアドバイス:スナップショットの負荷と間隔

筆者が現場でよく受ける質問の1つに、「スナップショットを取得すると性能に影響が出ませんか?」があります。筆者はいつもこんな風に答えています。「スナップショットを取る負荷はゼロではありません。しかし、スナップショットが変動要因となってパフォーマンスが急激に劣化するようでは、そもそものシステムリソースが足りない状況と判断できます。すぐにチューニングを行なうかリソースを増強してください」 また、「スナップショットの間隔はどれくらいが最適ですか?」という質問も、同じくらい受けます。この質問には、こう答えています。

「すべてのシステムにおいて一様に適用できる最適な間隔はありません。システムの特性とテスト時間の長さに依存します。例えば、負荷の変動が激しく、多様な特性を持った処理が流れるテストでは、5分~15分間隔で取得してください。一方、負荷が平坦で、同じような処理が繰り返されるようなテストでは、15分~30分間隔で取得してください。あとは、テスト全体の長さで調整しますが、あまり間隔が長いと負荷の増減が平均化されて性能劣化の原因を特定できない場合があります(図A)。また、スナップショットの間隔も大事ですが、テスト時間の前後の負荷がかかっていない状態でも数回スナップショットを取得することを忘れないでください」 恐らく、こうした質問はどのプロジェクトにおいても聞かれると思います。皆さんも必要に応じて工夫してみてください。

図A 実際の負荷とSTATSPACKから見える負荷とのギャップ

図A 実際の負荷とSTATSPACKから見える負荷とのギャップ

▲ ページTOPに戻る

絶対オススメ!テスト前に行なう2つの儀式

筆者が今まで幾度も経験し、そして自分自身も何度か犯したことのある失敗が2つあります。そのどちらも「こんな常識的で当たり前のことがなぜできなかったんだろう?」と思ってしまうような簡単な失敗です。常識的なこと、簡単なことほど意外に忘れやすいものなのです。筆者は現在、次に解説する2点については、パフォーマンステストの前に必ず行なうべき“儀式”であると肝に銘じています。

必ず、忘れず、アナライズ

データを揃え、アプリケーションも問題ありません。さて、パフォーマンステストをそのまま行なっても良いものでしょうか。多くのテストで忘れがちなのが、事前の統計情報の取得です。データをロードしたらすぐにテストを実施したい気持ちも分かりますが、統計情報も必ず本番環境と同じにしておきましょう。本番環境においてanalyzeコマンドを実行するのであれば同様にanalyzeコマンドを実行し、プランスタビリティ 注3を使用して実行計画を固定しているのであればそのように設定してください。性能が出ていないことに気が付いてからアナライズを行なうようでは、パフォーマンステストの正確性が疑われます。 少し脱線しますが、本番リリース直後に性能が出ないというトラブルが起きることもありますが、この理由の1つは移行作業にアナライズ 注4を含めていないことです。

意外に、パフォーマンステスト時にOracleの統計情報の取得を忘れることは多いものです。特にテスト期間に入り、多くのテストを過密スケジュールでこなすためにテスト環境が目まぐるしくスクラップ&ビルドを繰り返すときなどには要注意です。DBAは、必ず事前にOracleのアナライズ状態を確認することで、意図しないSQL実行計画による性能劣化を未然に防止します。 ぜひとも、パフォーマンステストを実施する前に「必ず、忘れず、アナライズ」の言葉を思い出して、必要であればアナライズを行なうようにしてください。

注3:Oracle8iから備わったSQL文の実行計画を固定する機能。初期化パラメータの変更や統計情報の取得を契機に起こる実行計画の変動が許されない場合に有効。 注4:ここでは、Analyzeコマンドによる統計情報収集も、DBMS_STATSによる統計情報収集も同じように“アナライズ”と表現しています。

テスト環境への不法侵入者はいませんか?

アナライズの次は、テスト環境に対する不正アクセスです。パフォーマンステストが妥当性を持つには、テスト期間中はテスト環境を占有していなければなりません。しかし、テスト期間中は混乱が付き物だということは前述のとおりです。パフォーマンステストを占有環境で実施できるはずだったにもかかわらず、常駐ジョブが実行されていたり、接続の切り忘れで負荷シミュレータ以外のアプリケーションが接続されていたり、「ちょっとだけ使っちゃおう!」という半ば確信犯的なゲリラ作業がなされていたりといったことは多々あります。

こういった意図しないアクセスがあったことに後から気付いた場合、多大なコストを払って再テストを実施しなくてはなりません。そうした事態を未然に防ぐために、筆者はテスト前に必ず不正なセッションの有無の確認と、可能であればOSやOracleの再起動を推奨しています。

OS上での常駐ジョブの有無を確認するには、UNIXの場合はcrontabコマンドなどを使用してください。Oracle上のジョブの有無を確認するには、SYSもしくはSYSTEMユーザーで直接Oracleに接続してLIST4のSQL文を実行します。DBA_JOBSビューは、現在Oracleに登録されているジョブの情報を表示します。各列の意味を表3に記します。

LIST4 Oracleのジョブ情報を表示する

LIST4 Oracleのジョブ情報を表示する

表3 dba_jobsの各列の意味

表3

OSに不正なログインが存在しているか否かを確認するには、UNIXの場合、whoコマンドなどを使用できます。Oracleに不正なアクセスが存在するか否かは、SYSもしくはSYSTEMユーザーで直接Oracleに接続して、LIST5のSQL文を実行して確認します。V$SESSIONビューには、現在Oracleに接続しているセッション情報が登録されています。その各列の意味は表4のとおりです。

LIST5 Oracleのセッション情報を表示する

LIST5 Oracleのセッション情報を表示する

表4 V$SESSIONビューの各列の意味

表4

もし、whoコマンドやV$SESSIONビューでテスト環境に対する不法侵入者を発見した場合、筆者は不正アクセスをしていた方に連絡して注意を促すだけでなく、プロジェクトの問題としても取り上げるようにしています。こうした問題は、その行為が故意か否かにかかわらず、プロジェクトにおけるテストスケジュールの管理が徹底されていないことが原因である場合が多く、都度の注意だけでは再発の恐れがあるからです。 以上、テスト前に行なっていただきたい2つの儀式を紹介しました。こうして確認してみると、意外と徹底できていないケースがあると納得していただけたのではないでしょうか。

▲ ページTOPに戻る

テスト環境のジレンマ

理想のテスト環境とは、本番環境と完全に同等のテスト環境であることは言うまでもありません。本番環境と同じスペックのサーバーやストレージ、本番環境と同じアプリケーションやデータなどが用意されている場合、その環境で発生した事象は必ず本番環境でも再現すると言えるでしょう。

しかし、テスト環境の整備は当然コストとのトレードオフとなるため、現実には理想的なテスト環境が用意されるとは限りません。皆さんも、コストの都合で本番環境を縮小させたスモールスケールのテスト環境しか準備できない中で「テストを行なっても本番環境とはまったく違う結果が出る。かといってテストを実施しないわけにはいかないし、やるからにはそれなりの結果を求められる」といったジレンマを抱えた経験があると思います。

こうした制限のある環境で行なわれたパフォーマンステストであっても、テスト結果を解析して本番環境における影響を推測し、チューニング項目のリストアップや性能の確保をしなければならないのがDBAです。ここで妥当性のある解析を導き出すには、制限のあるテスト環境がパフォーマンステストに与える影響について、またOracleに与える影響についても知っておかなければなりません。

ただし、本番環境より劣るテスト環境において目標をクリアしている場合には、特に問題ありません。ここからの話は、テスト環境では目標をクリアできなかった場合に、本番環境でクリアできるかを考える際の参考にしてください。 では、本番環境と異なるテスト環境のさまざまなケースを取り上げて、それらがOracleに与える影響と、その影響がテスト結果にどのように反映されるかについて解説します。

CPU数が異なる場合

CPU数に大きく依存するのは、処理の多重度とOracleのパラレル処理(パラレルクエリやパラレルDML)です。多重度が同じまま、CPU数の少ない環境でテストを行なった場合、CPU数に対する並列度が高すぎるため、実際は発生しない競合を起こす可能性があります。競合によって発生した待機処理のオーバーヘッドは本番環境では発生しないため、ボトルネックの箇所が本番環境と異なり、正しくチューニングが行なえません。当然スループットも、本番環境とテスト環境のCPU数の比率以上に劣化する可能性があります。

対策として、テスト環境のCPU数が本番環境よりも少ない場合、それに合わせて処理の多重度やパラレル度も変更してテストを行なってください。1つのCPUにかかる負荷や多重度が、本番環境と同等となるように調整します。テストから得られたスループットの値は、CPU数の比率を使って本番環境の値に換算して予測することも可能です。

ただし、やってはいけないのは、本番環境がマルチCPUであるにもかかわらず、テスト環境をシングルCPUにしてしまうことです。シングルCPU環境とマルチCPU環境ではハードウェアやソフトウェアの動作がまったく異なります。マルチCPU環境では、複数のCPUが協調しながら処理を行なうためのさまざまな仕組みが介在しますが、シングルCPU環境ではそういったことは一切考える必要がないからです。もし、本番環境が4CPUでテスト環境を2CPUにした場合と、同じく2CPUから1CPUにした場合では、同じようにCPU数を半分に減らした構成をとっていながらも、生じる影響の性質がまったく異なるのです。もし、「マルチCPU環境→シングルCPU環境」というスペックダウンによるテスト環境を用意されそうになった場合には、今述べた理由をしかるべき人に説明して、マルチCPU環境でテストを行なえるように説得してみてください。

CPUのクロック数が異なる場合

本番環境のサーバーとテスト環境のサーバーでCPUのクロック数(周波数)が異なるケースは、数が異なるケースよりもテスト結果の解析が困難です。CPUのクロック数が異なる場合、その影響はCPUに大きく依存する処理に顕著に現われます。Oracleが特にCPUを消費する処理には、セッションの確立、SQL文の解析、バッファキャッシュのスキャン、SQL*Loaderによるデータのロードなどがあります。

例えば、処理のたびにセッションの確立と切断を行なうようなシステムの場合(そもそも、このような仕組みはあまり推奨できませんが)や、短時間にセッションの確立が集中するようなシステムの場合、CPUクロック数が小さければ小さいほど、CPUネックに陥りやすくなります。そのため、負荷もテスト環境のクロック数に応じて調整する必要があります。

そのほかのCPUに依存する処理でも同様に考えます。SQL*Loaderを使用している最中は、その処理がCPUの平均使用率を押し上げるためにほかの業務処理が行なえない状況に陥ってしまう、つまりシステムがCPUネックとなる可能性があります。そうなってしまうと、システム本来のボトルネックの箇所はCPUネックの陰に隠れてしまい、もはやパフォーマンステストは意味をなしません。CPUネックとならないように全体の処理量の調整をしてください。

メモリの容量が異なる場合

メモリの容量が少ない場合に最も影響を受けるのは、OracleのSGA(System GlobalArea)のサイズです。ただ、SGAの中でもREDOログバッファは大規模システムでもたかだか数MBしかないのでメモリを圧迫しませんし、共有プールも大きければ大きいほどパフォーマンスが向上するものではないため、ORA-4031が発生しない程度にサイズを小さくしても問題ありません。SGAの中でもパフォーマンステストに最も影響があるのは、バッファキャッシュのヒット率です。

本番環境ではヒット率が95%以上のシステムであったとしても、メモリの制限によってサイズの小さくなったテスト環境のバッファキャッシュでは、ヒット率が下がるでしょう。かといって、低いキャッシュヒット率をすべてバッファキャッシュのサイズの責任にしてしまってはいけません。SQL詳細情報を見て、無用にフルスキャンをしている効率の悪いSQL文がないかを確認し、キャッシュヒット率が低いのはサイズのせいなのか、SQL文の実行計画が悪いのかを見極めましょう。ただ、そもそもテスト環境の制限でバッファキャッシュのサイズを小さくしなければならない場合は、「キャッシュの状態をイメージしよう」の節で解説したとおり、キャッシュサイズに合わせて使用するテストデータの容量も調整してください。

OracleのPGA(Program Global Area)もメモリ領域を必要とします。セッション数が多い場合、総PGAサイズも比例して大きくなるので、「気が付いたらスワップを起こしていた」なんてことにならないように注意してください。ソート処理やハッシュ結合はPGAサイズを多く必要とするので、多数のセッションから同時にこれらの処理を行なう場合は、セッション数を調整してPGAサイズを抑えることも検討してください。総PGAサイズの抑止のために、Oracle9iから導入されたPGAの自動調整機能の使用を検討しても良いでしょう。

ディスクの本数が異なる場合

テスト環境で用意できるディスクの本数が本番環境よりも少なくなる場合、本番環境では異なるディスクに配置されている予定のデータファイル同士がテスト環境では同じディスクに配置されてしまい、I/Oネックとなってしまうことが考えられます。OSのiostatコマンドが返すデータを監視しながら、なるべく各ディスクの処理量を平滑化して、I/O遅延がテストに影響を及ぼさないようにしてください。I/Oネックによって性能が頭打ちになってしまうと、パフォーマンステストの結果から本番環境の様子を予測することはもはや不可能です。

また、最近のストレージには大容量のディスクキャッシュが搭載される場合が多くなってきましたが、このメモリ容量の違いもディスクのレスポンスタイムに大きく影響します。具体的には、「db file sequential read」「dbfile scattered read」「log file parallelwrite」「log file sync」などのI/Oに関連する待機イベントのAvg wait(平均待ち時間)の値が、メモリサイズの増加に伴い改善されます(時間が短くなります)。分析の際には考慮するようにしてください。

以上、いくつかのパターンに分けて、スモールスケールのテスト環境が与える影響の代表的なものを解説しました。ここでは、基本的な概念と理解を促すために非常に単純化して書きましたが、実際には環境上の1つの変動要素がほかへ与える影響は多岐にわたるので、影響範囲と影響度合いを正確に把握することは不可能と言えます(そういう意味でも、やはり本番環境と同等スペックのテスト環境を、多少無理してでも用意していただきたいのです)。

したがって、環境が異なる場合のパフォーマンステストでは、結果の解析に知識だけでなく経験と勘を総動員して感覚的に行なっている部分も多々あるというのが正直なところです。ただ、こうしたときに勘が鋭く働くか否かは「○○が本番と異なるということは、××に影響が出るのでは?」と常に想像し考えているかにかかっています。本パートで説明したことは、そうした解析時に取るべき基本姿勢の足がかりとなるものだと思ってください。

▲ ページTOPに戻る

本番環境をイメージできるかが勝負

以上、筆者が体験したパフォーマンストラブルをもとに、トラブルを未然に防ぐパフォーマンステストのやり方、考え方について解説してきました。中には、それは理想論だと感じる箇所があったかもしれませんが、その理想論をどこまで実践してリスクを潰すか、潰せないリスクに関してはどのように考え、必要であればどんな対策をとるかが、DBAの腕の見せ所だと思っています。

本パート全体の根底にある基本姿勢は「本番環境をイメージする」ということです。本番の業務をイメージし、その業務でアプリケーションがOracleに対してどのようにアクセスをするかをイメージし、そして、最終的にはOracleの内部でどのように処理が行なわれるかをイメージします。そのイメージに可能な限り近づくようにパフォーマンステストを行なうことが、パフォーマンストラブルの種を摘み取る最良の近道です。

▲ ページTOPに戻る

"門外不出のOracle現場ワザ" インデックスに戻る

Copyright © 2009, Oracle Corporation Japan. All rights reserved.

無断転載を禁ず

この文書はあくまでも参考資料であり、掲載されている情報は予告なしに変更されることがあります。日本オラクル社は本書の内容に関していかなる保証もいたしません。また、本書の内容に関連したいかなる損害についても責任を負いかねます。

Oracleは米国Oracle Corporationの登録商標です。文中に参照されている各製品名及びサービス名は米国Oracle Corporationの商標または登録商標です。その他の製品名及びサービス名はそれぞれの所有者の商標または登録商標の可能性があります。

小田 圭二

小田 圭二(おだ けいじ) 1996年日本オラクル入社。人事教育本部にて、新卒や中途採用社員に対し、データベースやOS、ネットワークの講師を5年ほど経験した後、2000年にテクノロジーコンサルティング本部に異動。 テクノロジーのコンサルタントとして、主に大規模ミッションクリティカルシステムを担当。

ポリシーは、「OracleもOS上で動くアプリケーションにすぎない。だから、OS、ストレージ、ネットワークを学ぶべき」。 スキル面の興味は、アーキテクチャ、DBA、インフラ技術、教育、コンサル手法など。