Direct path read
目次[非表示]
- 1.基本情報
- 2.パラメータと待機時間
- 3.チェックポイントとソリューション
- 3.1.Parallel Queryの性能を高める
- 3.2.I/Oシステムの性能を高める
- 3.2.1.I/Oの概要
- 3.2.2.アプリケーション層(Application Layer)
- 3.2.3.Oracleのメモリ層(Oracle Memory Layer)
- 3.2.4.Oracleのセグメント層(Oracle Segment Layer)
- 3.2.5.OS/デバイス層(Device Layer)
- 3.2.6.Direct Path I/O
- 3.3._DB_FILE_DIRECT_IO_COUNTの調整
- 4.Event Tip
基本情報
direct path readイベントの待機は、Parallel Queryの実行時に、スレーブセッション(Slave Session)が実行されるdirect path I/Oによって引き起こされます。direct path I/Oは、SGA内のバッファキャッシュを経由せずにセッションのPGAに直接ブロックを読み込むことで、I/O方式(synchronous I/O、asynchronous I/O)に関係なく、実行されることがありますが、ハードウェアプラットフォームとDISK_ASYNCH_IOパラメータに影響を受けます。Direct read I/Oは、一般的に、ディスクの一時的(temporary)セグメントへのアクセス時に使用されます。これらの操作は、並べ替え(sort)、並列照会(parallel query)とハッシュ結合(hash join)の際に発生します。
注意:Oracle11gでは、並列処理ではなく、一般的なQueryでもTable Full ScanのDirect Path Readを実行することができます。したがって、既存のdb file scattered read待機イベントが観察されたQueryがOracle11gでdirect path readイベントを報告することになります。これについての詳細は、次のBlogポストを参照してください。
Disabling direct path read for the serial full table scan – 11g
スレーブセッションがdirect path readを実行中にコーディネータのセッション(Coordinator Session)は、スレーブセッションからの応答が来るのを待ってPX Deq:Excute Replyイベントを待機することが観察されます。Parallel Queryの実行時に発生するdirect path read待機は必然的なものです。もしdirect path readイベントの待機時間が過度に高く出た場合は、次のような観点から、チューニングポイントを見つけなければなりません。
このイベントの待機回数と待機時間は誤解を招く可能性があります。もし非同期I/Oが使用されていなかった場合、セッションは、I/Oが完了するまで待機します。しかし、I/O要求が開始された時点から待機時間を計算せずに、I/O要求が完了した後、データをアクセスするときにdirect path read待機イベントを待つことになります。したがって待ち時間はかなり短く表示されます。
もし非同期I/Oが使用可能で、現在使用している場合、セッションは多数のdirect read要求をした後、PGA内部にキャッシュされたブロックの処理を行います。セッションがPGAの内部にキャッシュされたブロックがなくて処理を進めていない時点でdirect path read待機イベントが発生しています。したがって、読み取り要求の回数は、待機回数と同じではありません。これらの不一致のために、V$ SYSTEM_EVENTおよびV$ SESSION_EVENTビューで表示されるdirect path read待機イベントの数値は信頼できないのです。
LOBセグメントを読み取るときに発生するdirect path read待機は、オラクル8.1.7からdirect path read(lob)待機イベントで別々に区分されます。
通常direct path read待機イベントは、一時的(temporary)または一般的な表スペースからdirect readオペレーションを実行するSQL文によって発生します。
ORDER BY、GROUP BY、UNION、DISTINCT、ROLLUPのようにソートが必要な関数を実行するSQL文は、PGA内で許可することができるよりも大きなデータを並べ替える必要がある場合、ソートラン(sort run)を一時テーブルスペースに記録します。一時テーブルスペースのソートランは最終的な結果を作成するために、順次PGAに読まれてマージされます。ソートランをPGAに読み込む間、そのセッションはdirect path read待機イベントを待機します。Hintまたはオプティマイザの判断によりMERGE結合を実行するSQL文も、並べ替え操作が必要となります。
ヒント(hint)またはオプティマイザの判断によってHASH結合を実行するSQL文は、PGA内で許可することができない大きさのハッシュパーティションを一時テーブルスペースに記録します。TEMPORARY表スペースに記録されたハッシュパーティションは、SQLステートメントの条件に一致するレコードを見つけるために戻ってPGAに読み込まれます。ハッシュパーティションをPGAに読み込む間、そのセッションはdirect path read待機イベントを待機します。
V$ SESSION_EVENTビューのTOTAL_WAITSまたはTIME_WAITED値を利用して、direct path read待機イベントを評価しない方が良いです。代わりに、次のクエリを使用して、大量のdirect readを実行しているセッションを見つけることができます。physical reads directはparentセッションによって開始されたdirect readsとparentセッションが管理するスレーブプロセスによって発生したすべてのdirect readsの合計で構成されています。
大量のdirect readsを発生させるセッションを見つけることに加えて、セッションがデータを読み取る位置(一時テーブルスペース、データファイルなど)、待機を発生させるSQL文を把握しなければなりません。次のクエリでは、これに対する答えを与えることができます。一時テーブルスペースからデータを読み取るセッションは、ソートやハッシュセグメントを読んでいるでしょう。データファイルからデータを読んでいるセッションは、並列クエリスレーブ(parallel query slave)です。
一時表スペースからソートセグメントを読んでいるセッションは、SORT_AREA_SIZE(または、Oracle 9iでPGA_AGGREGATE_TARGETを使用している場合、work area size)がメモリソートを実行するのに十分ではないことを意味します。しかし、これは問題にはなりません。すべてのソートがメモリでのみ実行されるのは、現実的に不可能だからです。しかし、多くのマルチパス(multi pass)ソートは可能な限り防止しなければなりません。なぜなら、マルチパスソートは、一時表スペースのかなりのI/Oを誘発し、非常に遅くなるからです。SQLステートメントがマルチパスソートをするかどのように確認できますか? Oracle 9iの以前のバージョンでは、容易ではありません。 10032トレースイベントを設定した後、トレースファイルを確認しなければならないのです。しかし、Oracle 9iのから、ソートを実行するSQL文のhash valueを使用して、V $ SQL_WORKAREAまたはV $ SQL_WORKAREA_ACTIVEビューを照会してみるだけでも、確認が可能となりました。ソートのさらなる詳細は、International Oracle Users Group(IOUG)2004 conference proceedings(www.ioug.org)の「If Your Memory Serves You Right」ホワイトペーパーを参照してください。
このような場合には、チューニングの目標は、ディスクソート回数を最小限にすることです。 SORT_AREA_SIZE(またはPGA_AGGREGATE_TARGET)のサイズを増加することにより、ディスクソートの回数を減らすことができます。しかし、これは非常にSORT_AREA_SIZEが小さく設定されている場合を除き、根本的な解決方法とは言えません。まず、アプリケーションでソートが必ず必要かを確認しなければならないのです。アプリケーションは、DISTINCTとUNION関数を濫用して使用する傾向があります。可能であればUNIONよりUNION ALLを使用して、SORT MERGEよりHASH結合、HASH結合ではなく、NESTED LOOPS結合を使用するようにしなければなりません。また、オプティマイザドライビングテーブルを正しく選択したかも確認する必要があります。結合インデックスのカラムをよく使われるORDER BY句とよく合うように設定しておけばソートを避けることもできます。 Oracle 9iのであれば、PGA_AGGREGATE_TARGETを使用してSQL work areaを自動的に割り当てして使うことができるように設定することも検討してのみましょう。統計的に見たときに、自動的にメモリ管理をするようにすると、メモリソートの割合をより高めてくれます。
セグメントを読んでいるセッションを発見した場合は、HASH_AREA_SIZE(Oracle 9iのでPGA_AGGREGATE_TARGETを使用している場合は、work area size)が小さく、メモリにハッシュテーブルを収容していない場合となります。解決方法は、既に述べなったものと類似しています。もしHASH_AREA_SIZEが小さすぎる場合でなければ、HASH_AREA_SIZE(またはPGA_AGGREGATE_TARGET)を調整する前に、まずアプリケーションとSQLステートメントをチューニングする必要があります。
もし並列クエリ(parallel query)スレーブでdirect readsが発生した場合、並列スキャン(parallel scan)がparent SQL文に適しているとスレーブの数が適しているかを確認しなければなりません。また、クエリスレーブがシステムのCPUとディスク・リソースをすべて使い果たしていないことを確認しなければなりません。Parent SQL問い合わせhash valueとクエリスレーブが実行するSQLのhash valueが同じではないので、parent SQL文を見つけることは容易ではないことでありません。オラクル8.1.5でV$ PX_SESSIONビューが導入されるまでは、さらに大変なことでした。下の2つの例では、、並列クエリが実行されるとparent SQL文を見つける方法を、Oracle8.1.5以前のバージョンとそれ以降のバージョンについて、それぞれ説明します。
パラメータと待機時間
待機パラメータ
Direct path read待機イベントの待機パラメータは以下の通りです。
|
待機時間
I/O関連のイベントなので、タイムアウトが発生せず、セッションは、I/Oが完了するまで待機します。
チェックポイントとソリューション
Parallel Queryの性能を高める
Parallel Queryを実行する過程でのdirect path read待機は必然的なもので、待機自体をチューニングすることは不可能です。むしろSQLチューニングを介してParallel Query自体の性能を改善させることが正しいアプローチとなります。システムの容量に比べて不必要にParallel Queryを実行することは、むしろ性能を低下させる要因となります。データファイルに直接読み取り操作を実行する前に、読み取りの対象となるオブジェクトのダーティブロックがデータ・ファイルに記録されなければならないというものがあります。つまりチェックポイントが発生するようになるのです。このタスクを実行する間、コーディネータのセッションは、enq:TC – contention待機が発生します。
I/Oシステムの性能を高める
I/Oの概要
I / Oは、Oracleで最も重要な資源です。Oracleが提供するすべての機能は、最終的にどのようにすれば、ファイルに対してよりよくデータをread/Writeするかに関するものです。したがって、自然にOracleのパフォーマンスの問題の多くは、I/Oと関連があります。I/OとOracleのパフォーマンスの問題を理解するには、オラクルでのI/O操作は、複数の層(Layer)で構成されているという事実を理解することです。オラクルでのI/O処理層を次のように分けて説明してみることにします。
- アプリケーション層:select/ insert/ update/ delete/ truncate…
- Oracleのメモリ層:Buffer cache|PGA
- Oracleのセグメント層:Datafile、tempfile、Tablespace、Segment
- OS/デバイス層:Asynch I/ O、Direct I/ O、Raw device、RAID、…
I/Oパフォーマンスの問題の原因を特定することと解決策を見つけるプロセスは、常に1 – >2 – >3 – >4の順に従ってください。論理的な面だけでなく、経済的な面でさらに有効となります。それぞれの層に必要な予備知識とメカニズムについて記述します。
アプリケーション層(Application Layer)
アプリケーションを効果的に実装して、不必要なI/Oを最小限に抑える必要があります。非効率的なアプリケーションをそのままにして、システムをチューニングすることはほとんど不可能です。Oracleは、I/Oを効率的に処理する様々なテクニックを提供します。Parallel Query、Parallel DML、Nologging、Direct load、Direct readなどが代表的な例となります。Oracleのバージョンが上がるほど、より効率的に作業を処理することができる強力なSQLの機能が追加されます。解析関数(Analytical Function)が代表的な例ですが、この関数をうまく利用すれば、I/Oを大幅に削減しながら、さまざまな集計機能を実装することができます。これらの最新のSQL文を使用して、I/O負荷を減らすようにしなければなりません。データの性質に応じて、クラスタ(Cluster)、IOT、パーティショニング(Partitioning)、ビットマップインデックス(Bitmap Index)などの機能を適切に使用して、I/Oを効果的に使用することも、アプリケーションで実装するべき機能となります。
Oracleのメモリ層(Oracle Memory Layer)
バッファキャッシュは、OracleのI/O管理の核心です。頻繁に使用するブロックをメモリにキャッシュすることにより、物理的なI/Oを減らすことができます。Oracleのバージョンが上がるにつれてバッファキャッシュを処理するアルゴリズムが絶えず改善され、加えて、新しい管理方法が提供されています。バッファキャッシュを効果的に使用すると、物理I/Oが減り、自然にI/Oパフォーマンスの問題が解決される場合が多くあります。Oracleが提供する機能には、次のようなものがあります。
|
Oracleのセグメント層(Oracle Segment Layer)
一般的なデータは、データファイルに格納されます。一時テーブルスペース(Temporary tablespace)を使用する場合は、基本的に、データファイルではなく、一時ファイル(Temp file)にデータを保存します。オラクル7.3以前のバージョンでは、ソート操作のために永続表スペース(Permanent Tablespace)を使用する必要でしたが、この場合、過剰なエクステントの割り当てと解放のために多くのパフォーマンスの問題が発生し、特にSTロック競合による性能低下現象が生じる場合が多くありました。オラクル8iから使用可能な一時テーブルスペース(Temporary tablespace)と一時ファイル(Tempfile)機能を使用すると、STロック競合は、もはや問題になりません。オラクル8iから提供されているLMT(Locally Managed Tablespace)とOracle 9iから提供されているASSM(Automatic Segment Space Management)を使用すると、エクステントとセグメント領域の不適切管理から来るパフォーマンスの問題のほとんどを解決することができます。大容量のテーブルは、パーティション(Partition)を利用して管理することが有利な場合が多くあります。管理的な側面だけでなく、大量のデータを処理する場合は、必要範囲のみをスキャンすることが可能ですので、必要なI/Oの範囲を減らす効果があります。
OS/デバイス層(Device Layer)
Oracleは、可能な場合は、非同期I/O(Asynchronous IO)を使用することを推奨します。非同期I/Oは、読み取り操作だけでなく、特にDBWRやLGWRなどの書き込み操作を実行するプロセスが非同期的にタスクを処理できるように処理してくれることでI/O操作の速度を全体的に改善させてくれます。残念ながら、多くのOSにおいて、真の非同期I/Oは、ローデバイス(Raw device)でのみ使用したことが知られています。非同期I/Oを使用することが不可能であればOSレベルでDirect I/Oを使用することが望ましいい方法です。Direct I/Oを使用する場合は、OSのバッファキャッシュをバイパスすることにより、不必要なI/O操作を最小限に抑えている。DBWRプロセスを複数個に使用することもひとつの方法です。
コントロールファイル(control file)の数やREDOログ・ファイルの数が不必要に多い場合は復旧が可能な分だけ維持することも有用となります。
Direct I/Oを使用する場合には、ローデバイスを使用する必要がないとの見方が多くあります。 Direct I/Oを使用する場合はOSのバッファキャッシュを経由しないため、その動作はローデバイスとほぼ同じだからです。しかし、ローデバイスがI/Oパフォーマンスの改善の重要な方法であるという事実自体は疑いの余地がないと思われます。
一つ留意することは、ローデバイスやDirect I/Oを非効率的に過剰に実行するアプリケーションの無条件的な解決策はないという事実です。例えば、非常に非効率的なI/Oを実行するアプリケーションの速度を改善するために、既存のファイルシステムをローデバイスに修正したと仮定しましょう。アプリケーションのパフォーマンスが向上するでしょうか?残念ながら、そうではない可能性があります。ローデバイスを使用することにより、I/O操作自体は速くなりますが、OSが提供するバッファキャッシュを使用していないからです。例えば、ファイルシステムを使用する場合には、100万回のPhysical Readのは実際には10万回のみ、実際のディスクの読み取りを誘発し、残りは90万回は、OSのバッファキャッシュから行うことができます。このような場合にローデバイスを使用すると、100万回のPhysical Readがすべてディスクの読み取りにつながるため、むしろアプリケーションケーションのパフォーマンスが低下することもあります。アプリケーションの適切なチューニングが常に優先であり、I/Oシステムのパフォーマンスの向上は、I/Oシステムが「実際に」遅い場合にのみ必要なのです。
RAIDで構成されたI/Oシステムを使用している場合には、RAIDレベル(level)を慎重に選択しなければなりません。 REDOログ・ファイルのように書き込み操作が豊富な資源のRAID-5を使用することは、パフォーマンスに大きな問題を起こします。データファイルの場合でも、RAID-5は、問題を引き起こす場合が多くあります。可能な場合はRAID1 + 0やRAID0 + 1を使用することが基本的な方法です。
ファイルを物理的に分離させることで、ディスクとの間の競合を避けることも重要となります。SANのように統合されたストレージシステムを利用する場合は、そのエンジニアとの協議を通じて、ファイル間での適切な分散が行われるように設定する必要があります。また、アーカイブモードでデータベースを操作する場合には、REDOログとアーカイブ・ログの間の競合が発生しないように構成してなければなりません。
I/Oシステムを変更することは多くの時間とお金を必要とする場合が多いため、常に最後の選択肢で残しておくなりません。 1〜4ステップで問題が解決されない場合にのみ、5段階目のチューニングとして考慮することが望ましい方法です。
RAIDの定義にのみ簡単に調べてみましょう。RAIDはRedundant Arrays of Inexpensive(Independent)Disksの略で、複数のディスクを組み合わせて、I/Oシステムを構成する技術をさします。ソフトウェア的に実装されることがありますが、性能面では、ハードウェア的に実装された方がはるかに有利です。
|
Oracleは、データファイルや制御ファイル、REDOログ・ファイルに対してRAID5よりRAID0+1またはRAID1+0を使用することを推奨します。RAID0+1は、物理的なストライピングに論理的なミラーリングを実装することをいい、RAID1+0は、物理的なミラーに論理的なストライピングを実装することを言います。
Direct Path I/O
OracleのI/Oは、基本的にSGA(バッファキャッシュ)を経由します。しかし、特殊な状況では、SGAを迂回してPGAにデータを上げます。データを共有する必要がないときは、バッファキャッシュにデータをロードする過程で発生するオーバーヘッドを回避することによって性能を改善することが可能です。バッファ・キャッシュ内の変更されたブロックをデータファイルに記録することはDBWR固有の作業です。一方、バッファキャッシュをバイパスする書き込み操作は、個々のプロセスが直接実行することになります。このように、バッファキャッシュをバイパスするI/O操作をdirect path I/Oと呼びます。Oracleは、次のような場合にdirect path I/Oを使用します。
|
Direct path I/Oに関連する統計値について整理すると、以下の通りとなります。
|
物理的な読み取り操作中にバッファキャッシュを経由した(conventional path I/O)読み取り操作は、次の式で計算することができます。
Direct path I/Oのパフォーマンスの問題は、ほとんどのI/Oシステムの性能と直接関連があります。Direct path I/Oは、バッファキャッシュを経由しないため、同期に伴うオーバーヘッドがありません。したがって、競合による性能低下現象が発生しません。並べ替え操作などの場合を除いては、チューニング作業を通じてdirect path I/Oでの待機回数と待機時間を減らすことは不可能です。もしdirect path I/Oの実行パフォーマンスに問題が生じると判断されると、I/O自体の性能を改善することに焦点を合わせることが正しい判断となります。
Oracleのdirect path I/Oは、OSのdirect I/Oとは別の概念であることに注意してください。Oracleのdirect path I/Oは、SGAのバッファ・キャッシュを経由していないものであり、OSのdirect I/Oは、OSのバッファキャッシュを経由しないでしょう。OracleのキャッシュとOSのキャッシュを併用することダブルバッファリング(double-buffering)と呼び、普通の性能によく無いないことが知られています。
しかし、ダブルバッファリングがパフォーマンスに及ぼす影響の程度は、システムの特性やアプリケーションの特性に応じて異なる場合があります。
_DB_FILE_DIRECT_IO_COUNTの調整
_DB_FILE_DIRECT_IO_COUNT隠しパラメータの値がdirect path I/Oでの最大I/Oバッファサイズを決定します。Oracle 9iのから、この値は、基本的に1Mの値を持ちます。しかし、実際にはO/Sやハードウェアの設定に応じて、最大値が決定されます。この値を大きくすると、Parallel Queryの性能が高くなる可能性がありますが、ほとんど実際の使用可能な値は、1Mよりも小さい値であるため、実際には変更する必要がありません。
Event Tip
irect path readとundo
direct path readにもかかわらず、データファイルからデータを直接読み取ることと、UNDOを参照するためのメカニズムは同じです。つまり、direct path readはSGAを経由していないだけで、読取り一貫性(Read consistency)を保証する方法は同じです。これを証明する方法は、サイズが小さい、UNDO表領域(Undo tablespace)を生成した後、Parallel Queryを実行しながら、別のセッションでDMLを過剰に行うと、ORA-01555(Snapshot too old)エラーを観察するものです。
上記のエラーはすぐにPQスレーブセッションがデータファイルのdirect readを実行しながら、変更されたブロックを検出すると、UNDOデータを参照するものと解釈することができます。
データファイルのdirect path readの証明
PQの実行時に、スレーブセッションでのdirect path readが一時領域ではなく、データファイルのdirect path readであることをどのように証明することができますか?一つのセッションでPQを実行した後、PQが実行される間に、他のセッションでV$ SESSION_WAITビューを照会してP1の値を取得するいくつかのファイルのdirect path readのか知ることができます。次のスクリプトを見てみましょう。
DB_FILE_DIRECT_IO_COUNT
DB_FILE_DIRECT_IO_COUNTパラメータはdirect path readパフォーマンスに影響を与えることができます。このパラメータは、direct reads、direct writesの最大I/Oバッファサイズに設定する必要があります。Oracle 8iまでは、ほとんどのプラットフォームで、デフォルトの設定値は、64ブロックでした。したがってDB_BLOCK_SIZEが8Kの場合direct reads、direct writesの最大I/Oバッファサイズは512K(8K*64)です。最大I/Oバッファサイズは、ハードウェアの限界値によっても制限されます。
Oracle 9iのではDB_FILE_DIRECT_IO_COUNTパラメータはhiddenパラメータで変更され、ブロック数ではなくバイト(byte)単位で変更されました。Oracle 9iのデフォルト設定値は1MBです。実質的なdirect I/Oサイズは、ハードウェアの設定(configuration)と限界値にも影響を受けます。
Direct Read I/Oサイズを知る
3つの方法で実際のdirect read I/ Oサイズを知ることができます。
前の例では、トレースファイルは、クエリスレーブ(query slave)#0の実行履歴です。direct pathオペレーションのために、32個のI/Oスロットが利用可能です(slot_cnt = 32)。一つのスロットが、I/Oユニットであり、それぞれのスロットは65536 bytesです(slot_size = 65536)。読み込みオペレーション時非同期I/Oが使用されています(async = 1)。クエリスレーブは、データファイルの#4を読みます(afn = 4)。読み込むブロック数は8個です(cnt = 8)。ブロックサイズは8Kであるため、65536 bytesを送信します。
この場合には、direct I/Oスロットのサイズは、プロセスが1MB全部を使用しないようにします。
_DB_FILE_DIRECT_IO_COUNTパラメータのデフォルト設定値は1MBです。スロットサイズは10351イベントを使用して変更することができます。また、スロットの数も10353イベントを使用して変更することができます。
(注意):前述の情報を利用して、自分が使用しているシステムのdirect I/Oのスループットを把握することができます。スロットサイズとdirect I/Oスロットの数のデフォルト設定値を簡単に変更しないでください。変更前に、自分が使用しているハードウェアの限界を把握する必要があり、アプリケーションとSQLステートメントを最適化させることに焦点を当てる必要があります。