また、CERNのデータベース専門家からの記事の翻訳を公開し続けています。 今日の資料は、SystemTapを使用したOracle DBパフォーマンスのトレースとデバッグに関する一連の記事の第2部です。

この記事では、SystemTapを使用してOracleの論理的および物理的な読み取り値を追跡することに焦点を当てています。 ここでは、物理的および論理的なI / Oを実行するためにOracleが使用する基本的なメカニズムを示すいくつかの例を紹介し、SystemTapスクリプトを作成してOracle I / Oを後で診断およびトラブルシューティングする方法を学びます
はじめに
メディアとの間で入出力を実行する、つまり 物理的な入出力は、すべてのデータベースエンジンの根底にある最も重要なタスクの1つです。 RAMのデータベースキャッシュに格納されたデータにアクセスするとき、 論理的な入力/出力について話すことができます 。 物理I / Oは、OSカーネルシステムコールを使用してデータベースによって実行されます。 使用されるシステムコールのタイプは、データベース、OS、およびストレージタイプによって異なります。 論理I / Oは、Oracleカーネル機能を使用するデータベースプロセスによって実行されます。 Oracleでは、 待機イベント・インタフェースを使用して物理I / Oコール時間の測定が提供され、論理I / O時間は一般にCPU時間とみなされます。 Oracleプロセスによって実行され、Oracle待機イベントインターフェイスによって提供される詳細によって補完されるI / Oトレースは、Oracleの内部 I / Oを調べるための強力な方法です。 いくつかの実際の例を使用して、Oracleがリポジトリにアクセスするために使用するメカニズム、I / O操作が待機イベントインターフェイスとどのように相関するか、また最も一般的なI / O待機イベントの時間率を見つけます。
トレースツールを作成する
I / O操作の実行時にOracleおよびOSが実行する操作の調査には、特別なツールが必要です。 SystemTapは、Linux用に特別に設計された動的トレースツールであり、OSとOracleの両方の機能(Linuxカーネル機能、システムコール、およびOracleデータベースカーネル機能)を追跡できます。 以下は、Oracleの論理および物理I / Oを追跡するために使用できるsystemtapスクリプトの説明です。対象の関数呼び出しを結合し、関数パラメーター、メモリ、およびプロセッサレジスタを読み取ることができるプローブで構成されます。
Systemtapでは、比較的最近のカーネルバージョンでユーザー空間のプロファイルを作成する必要があります:utraceまたはuprobe_events機能が利用可能でなければなりません。 たとえば、RHEL / OL 6.5以上が適切ですが、RHEL 5は適切ではありませんさらに、トレースシステムコールには、 debuginfoカーネルパッケージをインストールする必要があります 。
この記事で、 これとテスト環境の作成方法について詳しく読むことができます。 この投稿で使用する、Oracleの論理I / Oと物理I / O、および待機イベントインターフェイスをトレースするスクリプトは、 trace_oracle_logicalio_wait_events_physicalio_12102.stp (Oracle 12.1.0.2の場合)のようになります。 バージョン11.2.0.4では、オプションtrace_oracle_logicalio_wait_events_physicalio_11204.stpも使用できます。 Oracle I / Oのケーススタディに進む前に、スクリプトの3つの主要な部分、物理I / O、論理I / O、および待機イベントの追跡に注目します。
物理I / Oトラッキング
最終的に、OracleはI / Oを実行するシステムコールを行います。 呼び出しのタイプは、データベース設定、OSタイプ、およびストレージタイプによって異なります。 この記事では、ブロックデバイス上のASMストレージを使用したLinux上のOracleの例を見つけることができます。 asmlibを使用したダイレクトNFS、ローカルストレージ、ASMはこの記事には含まれておらず、今後の調査で検討される可能性があることに注意してください。 システムコールは、Linuxのstrace (1)ユーティリティを使用して追跡することもできます。 ただし、この記事では、SystemTapプローブを作成して、興味深いシステムコール( pread、pwrite、io_submit、io_getevents)に関する情報を収集する方法について説明します。 次のSystemTapプローブは、ブロックI / Oの基礎となる層に役立ちます:ioblock.request、ioblock_trace.request、ioblock.end(これらはシステムコールではなく、Linuxカーネル内の関数呼び出しのトレースポイントであることに注意してください)。
名前プローブ | 機能 | お気に入りのオプション |
syscall.pread / pwrite | 同期I / O:ファイル記述子の読み取り/書き込み | fd(ファイル記述子番号)、オフセット、番号。
戻り値:読み取り/書き込みバイト |
syscall.io_submit | 非同期I / O:処理のためのブロックの送信 | nr(入出力操作の数)。 各操作について:ファイル記述子、オフセット、バイト、操作コード(読み取りの場合は0、書き込みの場合は1)
戻り値:実行されたI / O操作の数 |
syscall.io_getevents | 非同期I / O:実行キューからイベントを読み取る | min_nr(読み取る入出力操作の最小数)、イベント待機のタイムアウト。
戻り値:収集されたI / O操作の数 各操作:ファイル記述子、オフセット、バイト。 |
ioblock.request、ioblock_trace.request | ブロックデバイスインターフェイスのカーネルレベルに送信されるI / O要求 | devname、セクター、サイズ、rw、block_io構造体アドレス |
ioblock.end | ブロックデバイスインターフェイスのカーネルレベルから戻る | devname、セクター、rw、block_io構造アドレス |
2015年8月に追加された注: kernel.trace( 'block_rq_issue')およびkernel.trace( 'block_rq_complete')の Systemtapプローブは、追加の利点を使用してブロックI / Oインターフェイスを調べるためにも使用できます:カーネルdebuginfoを必要としません。 そのようなプローブの例は、 ダウンロードページまたはGitHubで見つけることができます。
論理I / Oトラッキング
Oracleがメモリ(バッファキャッシュ)からデータのブロックを読み取るときの論理I / Oの履歴と詳細についてです。 論理I / O操作には、物理I / O操作のサブセットが含まれます。Oracleがメモリ( バッファキャッシュ )でデータを見つけられない場合、物理的な読み取りを実行します。 この記事の後半で実際にこのメカニズムの例をいくつか見つけることができます。
Oracleツールキットは、 V $ SYSSTAT 、V $ SESSTAT、V $ SYSMETRICなど、複数のV $ビューで論理読み取りに関する広範な情報を提供します。 論理読み取りデータは、sql *に加えて、「set autotrace on」パラメーターとtkprofでイベントトレース10046をレポートすることもできます。 論理読み取り値には、一貫性と最新の2つの主な形式があります。 Oracleは、特定のシステム変更番号SCNのデータを読み取るときに一貫した読み取りを使用し、ブロックでDML操作を実行するときに現在の読み取りを使用します。 イベント10200および10201を使用して、一貫した読み取りをOracleでトレースできます。 詳細については、 Julian Dykeの論理I / Oに関するプレゼンテーションを参照してください。
この記事では、プローブSystemTapをOracleカーネル機能セットに接続して、論理I / Oを追跡する方法を示します。 一貫性のある現在の読み取りトレースに対するkcbgtcrおよびkcbgcur関数の役割は、Alexander Anokhinの優れたDtrace LIO記事ですでに説明されています。 最近、このトピックを調査し、関数kcbzib、kcbzgb、kcbzvbをトレースすることも有用であることがわかりました 。
これらの機能についてわかったことの概要を以下の表に示します。 注:%rdi、%rsi、%r8式は、対応するプロセッサレジスタの値を示します。 SystemTapを使用すると、register関数を使用してレジスタ値を読み取ることができます。例:register( 'rdi')。 CPUレジスターは、 関数呼び出し引数を抽出するために使用されます 。 Systemtapは、実行可能ファイルのデバッグシンボルがない場合、関数呼び出し引数を提供しません。 特に、 www.x86-64.org/documentation/abi.pdfで説明されているx86-64の呼び出し規則は、関数を呼び出すための整数パラメーターが次のレジスターで(順番に)使用可能であることを示しています:%rdi、%rsi 、%rdx、%rcx、%r8および%r9。
機能名 | 進行中のタスク | お気に入りのオプション |
kcbgtcr | カーネルキャッシュバッファーの一貫した読み取り
一貫した読み取りに使用 | tbs#= user_int32(%rdi)
rel file n#= user_int32(%rdi + 4)>> 22&0x003FFFFF ブロック#= user_int32(%rdi + 4)&0x003FFFFF data_object_id#= user_int32(%rdi + 8) object_id#= user_int32(%rdi + 12) 注:大きなファイルの表領域の場合: ブロック#= user_int32(%rdi + 4) |
kcbgcur | 現在のカーネルキャッシュバッファー
現在の読み取りに使用 | tbs#= user_int32(%rdi)
rel file n#= user_int32(%rdi + 4)>> 22&0x003FFFFF ブロック#= user_int32(%rdi + 4)&0x003FFFFF data_object_id#= user_int32(%rdi + 8) object_id#= user_int32(%rdi + 12) 注:大きなファイルの表領域の場合: ブロック#= user_int32(%rdi + 4) |
kcbzib | kcbZIBは、Z(kcbz.o-物理入出力の補助機能用モジュール)、IB:入力バッファーの略です。
Oracleは、バッファキャッシュに対して物理的な読み取りを実行します。 | |
kcbzgb | kcbZGBのGBサフィックスは、バッファーの取得(スペース)を表します
Oracleは、特定のブロック(通常はI / Oの前)にバッファ領域を割り当てます。 | tbs n#=%rsi、
rel file n#=%rdx >> 22&0x003FFFFF ブロック#=%rdx&0x003FFFFF data_object_id#=%r8 object_id#=%r9 注:大きなファイルの表領域の場合: ブロック番号=%rdx |
kcbzvb | Oracleが指定されたブロックを読み取った後に呼び出されます。
これは、db_block_checkingパラメーターによって制御されるブロックをチェックするための呼び出しチェーンの一部です。 推定復号化:カーネルキャッシュバッファー検証ブロック。 この説明をありがとう@FritsHoogland この関数は、バッファキャッシュの読み取りと直接読み取りの両方に使用されます。 | tbs n#=%rsi、
rel file n#=%rdx >> 22&0x003FFFFF、 ブロック#=%rdx&0x003FFFFF data_object_id = user_int32(%rdi + 24) 注:大きなファイルの表領域の場合: ブロック番号=%rdx |
注 :執筆時点では、バージョン3.10以降のカーネルのアップローブのみがユーザー空間関数のプローブを返していました。 したがって、この機能はRHELまたはOL 6.xでは使用できませんが、RHEL 7.xカーネルでは使用できます。
待機イベントを追跡する
待機イベントインターフェイスは、パフォーマンスの問題とボトルネックを特定するための定量的な方法を提供するため、おそらくOracleパフォーマンスのチューニングで最も優れた機能の 1つです。 Cary Millsapは 、このテーマに関するインスピレーションを与える作品を発表しています。
この目的のために、待機イベントは、Oracleカーネルの選択されたアクションが測定される計測ポイントであることを示すことで十分です。 特に、Oracleはほとんどの物理I / O操作の開始コールと終了コールをマークするため、物理I / Oのプロセスに費やされる時間を十分に理解できます(このメカニズムの制限については、この投稿で後述します)。 待機イベントインターフェースを使用してI / Oレイテンシを調査することには制限があります。特に、例のセクションでは、 非同期 I / Oイベントの継続時間の測定に関連する興味深いタスクを見つけることができます。
通常、待機イベントのトレースは、Oracleでイベント10046を使用するか、DBMS_MONITOR.SESSION_TRACE_ENABLEを呼び出してアクティブにします。 この記事では、プローブSystemTapをOracleカーネルの対応する関数( kskthbwtおよびkskthewt )に接続して 、各待機イベントの開始時と終了時に情報を収集することにより、待機イベントに関する詳細情報を取得します。 レベル8のイベント10046およびその他のメソッドを使用して待機イベントトレースを有効にすることは、待機イベントの時間に関する情報(およびSQL処理に関するその他の詳細)を取得する方法であり、待機情報を含める方法ではありません。 次に、これはTIMED_STATISTICSデータベースパラメータを使用して行われます。最新のOracleデータベースでは、TRUEに設定する必要があります。 Oracleカーネルのkskthbwtおよびkskthewt関数によって提供される情報の重要な部分は、 X $ KSUSEサービステーブル (または、SGAの「基礎となる」メモリ構造) へのポインタです 。したがって、待機イベントと、SQLを実行しているセッションに関する多くの有用な情報を一致させることができます。 レジスターr13のポインターをX $ KSUSEのベース値に逆参照し、対象のフィールドのオフセットを計算するには、前の記事で詳しく説明した追加の作業が必要です(スクリプト: ksuse_find_offsets.sqlも参照)。
機能名 | 進行中のタスク | お気に入りのオプション |
kskthbwt | カーネルサービスKompileスレッドは待機を開始します。
この関数は、Oracle待機イベントの開始時に呼び出されます。 kslwtbctxはその親関数の呼び出しであり、待機イベントの開始をマークします。 | 関数のプロファイリングに役立つ情報:
レジスタr13-> SGAのX $ KSUSE(V $ SESSION)のセグメント化された配列を指します register rsi->待機開始のタイムスタンプ(マイクロ秒) レジスタrdx->待機イベントの数 |
kskthewt | カーネルサービスKompileスレッド終了待機。
この関数は、Oracle待機イベントの終了時に呼び出されます。 kslwtectx-待機イベントの終了をマークする親関数の呼び出し。 接尾辞「ewt」は、「end wait」を意味する可能性があります。 | 関数のプロファイリングに役立つ情報:
レジスタr13-> SGAのX $ KSUSE(V $ SESSION)のセグメント化された配列を指します register rdi->待機開始のタイムスタンプ(マイクロ秒) 登録rsi->待機イベントの数 |
スクリプト実行
以下に、一般的なOracle I / Oアクセスパターンのトレース例を示します。 トレースは、コマンドstap -v trace_oracle_logicalio_wait_events_physicalio_12102.stp -x _pid_で受信されました。ここで、_pid_は、監視対象セッションのプロセスの識別子です。 結果はsed -f eventsname.sedに渡され、そこでイベント番号がそれに関連付けられた名前に変換されます。 eventsname.sedファイルは、eventsname.sqlスクリプトを実行して作成されます。 テスト前にスクリプトを再起動してイベント名を生成することが重要です。待機イベントの数は、新しいバージョンへの移行後やパッチのインストール後など、警告なしに変更される可能性があるためです。 次の例でトレースを収集するために使用されるシステムは、VirtualBoxの下でUEK3を使用してOEL 7.0で実行されるOracle 12.1.0.2です。
例1:単一ブロックのランダム読み取り
この例は、単一ブロックのランダム読み取りのカテゴリに属します。 このデータアクセス方法は、インデックスキーを介してテーブルにアクセスするために使用されるため、多くのOLTPワークロードにとって非常に重要です。 以下の図1では、indexed_col = valのテーブルタブからcol_listを選択するタイプのクエリのトレースファイルのフラグメントを見ることができます。

図 1:dbファイルからのOracleシングルブロックランダム読み取りおよび順次読み取り待機イベント
キーポイント :
- この例では、 OracleはSQLのデータを取得するために必要なブロックの1つを論理的に読み取ります。
- 論理読み取り呼び出しには追加情報が含まれています。これは、Oracleがobj#= 32174(この例ではテーブルセグメント)が所有するtbs#= 7からブロック#= 2505675を読み取ることを示しています。
- キャッシュでブロックが見つからなかったため、バッファキャッシュに新しいブロックが割り当てられ、物理的な読み取りが開始されます。
- データベースは、「dbファイルの順次読み取り」の待機イベントの開始をマークします。
- ブロックに対する物理的な読み取り要求は、OSへの事前呼び出しになります。
- IOリクエストはシステムコールを介してカーネルに到着します。 システムコールが終了してユーザーランド(この場合はOracle実行可能ファイル)で終了するまで、システムコールの後に発生する関数はカーネル関数(ioblock.requestなど)です。
- この読み取り関数の呼び出しは、ブロックI / Oインターフェイスに渡され、ブロックデバイス(図1の例では/ dev / sdl)から8192バイト (1データベースブロック) を読み取ります 。
- ブロックインターフェイス、そしてOS呼び出しは、読み取りデータをOracleカーネルに返します。
- Oracle待機インターフェースは、待機の完了をマークし、経過時間を計算します。
- 待機イベント-「dbファイル順次読み取り」、パラメーター:p1-ファイル番号、p2-ブロック番号、p3-読み取られたブロック数(1ブロック)。
- トレースのタイムスタンプ値から、 シーケンシャル読み取りdbファイルの待機時間は 、ほとんどオーバーヘッドなしでpread呼び出しを完了するのにかかった時間に依存することがわかります (高負荷の場合、オーバーヘッドがより大きくなることに注意してください)データベースサーバーのCPU。たとえば、他のOracleセッションからのワークロードが原因です。
- この例では、シーケンシャル読み取りdbファイルの測定レイテンシーは、物理読み取りに関連する遅延に対応すると結論付けることができます 。
例2:同期I / Oを使用したバッファーキャッシュへの順次I / O
この例では、キャッシュ内のマルチブロック読み取りを扱います。 これは、たとえばOracleが全表スキャンを実行するときに使用されるアクセス方法です。 Oracleがリポジトリにアクセスして全表スキャンを実行する方法はいくつかあります。この例では、Oracleが同期I / O(つまり、preadコール)を使用してOS読取り操作を実行する場合を示しています。例3および4非同期I / Oによる順次読み取りをカバーします。 下の図2では、 テーブルタブselect col_listなどのクエリのワークロードを追跡するためのスニペットを見ることができます。Oracleはテーブルタブのフルスキャンを実行します。

図 2:pread OS呼び出しを使用して読み取りが行われる場合のOracle Sequential I / O
図2の主要なトレースポイント :
- Oracleは、tbs#= 7ブロック#= 2621443の順次読み取りを提供し、キャッシュでそれを見つけます。
- Oracleは、次のブロックに対して一貫した読み取りを実行しますが、キャッシュ内でそれを見つけられないため、1回の物理読み取りでストレージからブロックのリストを読み取る準備をします 。 このリストは124ブロックで構成されています(この例では簡単にするために短縮されています)。
- データベースは、 dbファイルの分散読み取り待機イベントの開始をマークします 。
- 物理的な読み取り要求は、1015808バイト(124ブロック)を受信するためのOSへの単一の事前呼び出しになります。
- テストに使用されるシステムのI / Oの最大サイズは524288バイトであるため、この要求はI / Oチェーンを下ってブロックI / Oインターフェイスに移動し、「基になる」ブロックデバイスから2つの読み取りに分割します。
- Fritz Hooglandの調査によると、送信されたI / OリクエストはI / Oスケジューラのスキャッター/ギャザーリストに配置され、ブロックデバイスによって宣言されたI / Oサイズに分解されます。
- 入出力は、ブロック入出力インターフェースによって実行されます。
- 呼び出しの呼び出しを返します。
- 待機イベントインターフェイスは、待機の終了時間をマークします
- 待機イベントはdbファイル分散読み取りであり、パラメーター:p1はファイル番号、p2はブロック番号、p3はブロック数です。
- トレースのタイムスタンプ値から、 dbファイルの分散読み取り待機の期間は、主にほとんどオーバーヘッドなしでpread呼び出しを完了するのにかかった時間が原因であることがわかります 。
- Oracleカーネルのkcbzvb関数の呼び出しのトレースから、読み取られたブロックの追加の確認を取得します。
- この例では、分散読み取りdbファイルの待ち時間はI / O遅延に対応すると結論付けることができます。
例3:OS非同期I / O関数呼び出しによるバッファーキャッシュへの順次I / O
図3では、SQLトレースのフラグメントが表示されており、 テーブルタブからcol_listを選択しています 。ここで、Oracleはテーブルタブの完全スキャンを実行します。 これは、例2で使用したのと同じクエリです。違いは、図3のトレースが、Oracleプロセスがpread呼び出しによる同期I / Oの使用から非同期 I / O インターフェイスの使用に切り替えたときに、クエリの後の段階で行われたことです。 非同期I / Oは、I / O要求を送信して結果を取得するio_submitおよびio_getevents呼び出しによってLinuxに実装されます。 この例では、Oracleは非同期インターフェイスを使用して読み取り操作を実行しますが、最終結果は例2で示した結果と非常によく似ています(つまり、同期I / Oを使用)。 同じOracle待機イベント“ db filescattered read” 、読み取りもバッファキャッシュで実行され、I / O結果はブロック呼び出しを使用して収集され、実際にプロセスを同期化します。 以下の例4で説明する直接読み取りを実行すると、Oracleでは非同期I / Oのインターフェイスの「積極的な使用」が発生します。

図 3:非同期I / O呼び出しを使用してバッファキャッシュへの順次I / O読み取りを実行するOracle
キーポイント :
- Oracleは、tbs#= 7 block#= 2522760に対して一貫した読み取りを実行しますが、キャッシュ内でそれを見つけられないため、バッファキャッシュ内のブロックのリストを読み取る準備をします。 このリストは128ブロックで構成され、この例では短縮されています。
- データベースは、 「db filescattered read」の待機イベントの開始をマークします 。
- 物理読み取り要求は、合計サイズが1 MB(つまり、128ブロック)の2つの要求を持つio_submit呼び出しとしてOSに転送されます。最初の読み取り要求(オペレーションコード0)は65,536バイトで、2番目は983040バイト(つまり1 MB)からの読み取りです-64 KB)。
- これらの要求はブロックI / Oインターフェイスに渡されます。ブロックI / Oインターフェイスは、基盤となるブロックデバイス(この例では/ dev / sdi)からの2回の読み取りに対する最大の要求を共有します 。 64 KBの読み取り値は、サイズ変更せずに/ dev / sdrに転送されます。
- Oracleはio_geteventsを呼び出して、送信されたばかりの非同期I / O要求の結果を取得して待機します。 timeout.tv_secフィールドは600に設定されます。これは、min_nr = 2 IO操作を完了するためのブロッキング待機 (つまり、io_geteventsが600秒(tv_sec)と0ナノ秒(tv_nsec)を待機する)であることを示します。
- ブロックデバイスインターフェイスは、データを呼び出しチェーンに返します。
- io_getevents呼び出しは2つの読み取りを返します。
- 待機イベントインターフェイスは、待機の終了をマークします。 この場合の待機イベントは、dbファイルの分散読み取りです。
- 待機イベントのパラメーター:p1-ファイル番号、p2-ブロック番号、p3-ブロック数。
- 待機イベントの期間は、基本的にio_submitおよびio_geteventsの呼び出しに費やされた時間にわずかなオーバーヘッドを加えたものです。
- Oracleは非同期インターフェースを使用しましたが、すべてのI / Oが完了することも期待していたため、I / Oは実際には同期です。
- kcbzvbの呼び出しから、読み取られたブロックの追加の確認を取得します。
- 結論:この例の散在読み取りdbファイルの待ち時間は、2つの異なるデバイスでの2つの読み取りが同時に要求され 、合計時間が単一の読み取りであるかのように反映されるため、 I / O待ち時間の正確な指標ではありません 。
例4:直接読み取りと非同期I / Oを使用したフルスキャン
この項では、 ASMを使用して構成されたブロック記憶域での直接読取りの場合のOracle I / Oの2つの例を示します。 例2および3と同じ全テーブルスキャンを実行する同じクエリを使用します。この例では、例2および3とは異なり、Oracleはシリアルダイレクトリードを使用してデータにアクセスします。 シリアルダイレクトリードは、11gR2で導入された機能で、フルセグメントスキャン操作を最適化し、バッファキャッシュレイヤーをバイパスします。これは、並列リクエストで発生するものと同様です。 Oracleは、いくつかのパラメーターに基づいて、キャッシュ読み取りの代わりにシリアル直接読み取りをいつ使用するかを選択します。 最初の近似では、バッファキャッシュのサイズと比較してテーブルが「大きい」場合は直接読み取りが望ましいですが、実際のメカニズムはより複雑であり、Oracleのバージョンに応じて変更される可能性があります。 このトピックの詳細については、 Tanel Poderの記事をご覧ください 。
これらのテストを実行するには、リクエストを実行する前にシリアルダイレクトリードの使用を強制する必要がありました。これは、 alter session set "_serial_direct_read" = always; 。
リクエスト変更セッションセット "_serial_direct_read" = never; シリアルダイレクトリードを無効にして、Oracleにキャッシュリード(つまり、上記の例2および3で見たI / Oのタイプ)を使用させることができます。 _serial_direct_readパラメーターのデフォルト値はautoです。
この例の研究では、以前のものとは少し異なるSystemTapプローブを使用できます。 - - , probe userspace io_getevents_0_4 libaio (libaio — Linux, -). , serial direct reads -, libaio , (Frits Hoogland) . SystemTap, . 4a 4, : trace_oracle_wait_events_asyncio_libaio_12102.stp ( 11.2.0.4 trace_oracle_wait_events_asyncio_libaio_11204.stp ).

図 4a: Oracle I/O full table scan serial direct read -. , full scan
4a:
- Oracle - 1 . , , readahead, .
- 1 db_file_multiblock_read_count=128, — 8 .
- Oracle - 1 io_submit , io_getevents_0_4 libiao, , . , - . Oracle 1 4 - ( - ).
- io_getevents, -, ( 600 ).
- «direct path read» .
- Oracle - io_getevents .
- - Oracle .
- 2 , 1 .
- - :
- «direct path read» 128 (1 MB), 2 MB.
- «direct path read» - .
- Oracle io_getevents, -.
- Oracle 2 .
serial direct reads Oracle , , . 4a. direct reads Oracle . , Oracle direct reads , . - -. I/O slots. , Oracle 10353 : « (slots) — -, -».
, -, direct reads, . , Oracle io_getevents timeout=0, - . . 4. full scan, 4, , adaptive serial direct reads Oracle I/O, « » .

図 4. Oracle I/O full table scan serial direct read -. , , -
4:
- full scan, . 4a. , 4 full scan ( 1 ), adaptive serial direct reads - ( -).
- , io_submit .
- Oracle -: - 4, 4a (.. full scan) 2 .
- - io_getevents Oracle :
- , 1 , io_getevents , .
- , Oracle - io_getevents ( io_getevents_0_4 libaio, - -) 0, , Oracle , - , , .
- , Oracle " direct path read ", 3 io_getevents ( -, 600, ), 9 , 1 .
- - :
- 1 (128 ), 9 .
- 2 instrumentation .
- «db file direct read» - , , , -, 4.
- - :
5: - random reads
Oracle single-block reads , / -. random I/O -, Oracle - io_submit, , 1, pread OS. . 5 SLOB (Kevin Closson) 12c. 3 , Oracle «TABLE ACCESS BY INDEX ROWID BATCHED» .

図 5: SLOB, (batch access)
6 Oracle I/O SLOB. , - random I/O. , . 6, 126 io_submit, io_getevents, . — «db file parallel read», — 126 . db file parallel read - single block random reads .

図 6: Oracle, - -, batched reads. ( 126 , block#) "..."
6: DML
7 Oracle logical I/O , . - ( ). , current read, DML. , ( 7 tbs#=11), rollback segments ( 7 tbs#=2). , .

図 7: Oracle logical I/O, commit
7: log writer
8 log writer commit. commit, 6 (. . 7 ). — «log file parallel write», Oracle -. , «log file parallel write» , . , 8, , log writer , 1 redo- , ASM- normal: log writer 2 - — - — .

図 8: log writer commit
おわりに
, , SystemTap Oracle I/O, Oracle I/O Oracle Linux. , , .
Oracle Oracle I/O OS , Oracle. Oracle - - . random reads, «db file sequential read». , , -, : -. , , - Oracle direct reads .
: この作品にインスピレーションを与えた独創的なアイデア。この問題に関する彼の深い専門知識を私にgeneしみなく分かち合ってくれたフリッツ・フーランドに感謝します。
スクリプトのダウンロード:この記事で説明したスクリプトは、ダウンロード資料のあるWebページまたはGitHubから入手できます。