ABAP コードをプロファイリングすることで、データベースへのアクセスが実行時間全体に大きく貢献していることがわかりました。次に、SQL トレースツールを使用して、プログラムのデータベースアクセスをより詳細に分析し、コードのパフォーマンスをさらに改善します。
タスク 1: テンプレートのコピー (オプション)
テンプレートクラス /LRN/CL_S4D401_ATS_PROFILING をコピーします。前の演習問題を完了した場合は、このタスクをスキップし、クラス ZCL_##_SOLUTION の編集を続行することができます。
ステップ
クラス /LRN/CL_S4D401_ATS_PROFILING を各自のパッケージのクラスにコピーします (推奨名: ZCL_##_SOLUTION、## はグループ番号)。
Project Explorer で、クラス /LRN/CL_S4D401_ATS_PROFILING を右クリックしてコンテキストメニューを開きます。
コンテキストメニューから Duplicate.... を選択します。
Package 項目にパッケージの名称を入力します。Name 項目に、ZCL_##_SOLUTION (## はグループ番号) と入力します。
Next を選択します。
移送依頼を確認し、Finish を選択します。
コピーを有効化します。
Ctrl + F3 を押してクラスを有効化します。
タスク 2: SQL トレースの実行
パフォーマンスの問題をさらに分析するには、SQL トレースを有効化し、ABAP クラス ZCL_##_SOLUTION をコンソールアプリとして実行します。
同じ ABAP インスタンス内では、一度に 1 人のユーザのみが SQL トレースをオンに切り替えることができます。他のユーザに機会を付与するには、コンソールアプリケーションの実行が終了したら、SQL トレースをオフにします。
ステップ
開いていない場合は、エディタで ABAP クラス ZCL_##_SOLUTION を開きます。
Ctrl + Shift + A を押して、ABAP クラスの名称を入力します。
OK を選択します。
ABAP クラウドプロジェクトの SQL トレースステータスダイアログを開きます。
左側の Project Explorer で、プロジェクトを右クリックしてコンテキストメニューを開きます。
SQL トレース .... を選択します。
現在の SQL トレースステータスをチェックします。トレースがオンになっている場合は、ダイアログウィンドウを閉じて数分後に戻ります。
OK を選択して、ダイアログウィンドウを閉じます。
トレースが現在オフになっている場合は、オンに切り替えます。次に、ダイアログウィンドウを閉じます。
有効化を選択して、SQL トレースをオンに切り替えます。
OK を選択して、ダイアログウィンドウを閉じます。
グローバルクラス ZCL_##_SOLUTION をコンソールアプリとして実行します。
F9 を押して、ABAP クラスをコンソールアプリとして実行します。
アプリケーションが終了したらすぐに、SQL トレースをオフにして、トレースディレクトリを開きます。
右下隅の緑色の進捗インジケータが消えたら、Project Explorer でプロジェクトを右クリックし、SQL Trace .... を選択します。
無効化を選択して、SQL トレースをオフにします。
トレースディレクトリを表示を選択して、トレースの一覧を表示します。
タスク 3: トレース結果の分析
SQL トレース結果を分析します。ABAP クラスから発生するデータベースアクセスをフィルタリングし、どのデータベーステーブルがどのくらいの頻度でアクセスされたかを調べます。
ステップ
DB/OS コックピットで、最新のトレースのトレースレコードを照会します。
ヒント
デフォルトでは、トレースの一覧はタイムスタンプ列の降順でソートされます。
最上位の一覧エントリを選択します。
トレースレコードを選択します。
トレースレコードの一覧をフィルタリングします。ABAP クラス ZCL_##_SOLUTION からのレコードのみを表示します。
ヒント
プログラム列ヘッダを選択して設定できる表示フィルタではなく、Go ボタンの左側にあるフィルタオプションを使用することをお奨めします。
テーブルのツールバーで、開始ボタンの左側にあるフィルタ (...) オプションを選択します。
ダイアログウィンドウの上部にあるドロップダウンリストからプログラムを選択します。
類似オプションが選択されていることを確認します。
Enter value というプロンプトを ABAP クラスの名称 (ZCL_##_SOLUTION) に置き換えます。
OK を選択します。
開始を選択して、テーブルエントリを更新します。
トレースレコードの一覧をソートします。最も多くのレコードにアクセスした SQL 文を検索します。
注記
デフォルトでは、トレースレコードの一覧はタイムスタンプ列でソートされます。ソートを変更するには、最初に既存のソートを削除する必要があります。
Go ボタンの右側にある 3 つの水平ドットを選択します。
ソートリセットを選択します。
テーブルのツールバーで、開始ボタンの左側にあるソート (0) オプションを選択します。
アクセス済レコード [#] 列を見つけます。左側のボックスにチェックを付け、この列に対して降順ソートボタンを選択します。
OK を選択して、ダイアログウィンドウを閉じます。
実行を選択します。
アクセス済レコード列によるソートを削除し、一覧を期間列の降順でソートします。
Go ボタンの右側にある 3 つの水平ドットを選択します。
ソートリセットを選択します。
テーブルのツールバーで、開始ボタンの左側にあるソート (0) オプションを選択します。
Duration [µs] 列を見つけます。左側のボックスにチェックを付け、この列に対して降順ソートボタンを選択します。
OK を選択して、ダイアログウィンドウを閉じます。
実行を選択します。
最も負荷の高い単一レコード文については、SQL 文セクションにナビゲートします。
アクセス済レコード列で値 1 の行を選択し、期間列で最大値を選択します。
上部のナビゲーションペインから SQL 文を選択します。
FROM 句でテーブル名を検索します。
ABAP 開発ツールで SELECT 文を開きます。
ADT で ABAP ソース表示を選択します。
タスク 4: コードの改善
コードのパフォーマンスをさらに改善するには、データベーステーブル /LRN/CONNECTION への繰り返される SELECT SINGLE アクセスを削除します。テーブル /LRN/CONNECTION には比較的少数のレコードが含まれています。そのため、データベーステーブルのコンテンツ全体を静的属性にバッファすることにしました (推奨名: connections_buffer)。静的コンストラクタ (メソッド class_constructor) でバッファに入力し、SELECT SINGLE 命令をバッファへの読込アクセスに置き換えます。
ヒント
データベーステーブル /LRN/CONNECTION への SELECT SINGLE アクセスは、ローカルクラス lcl_passenger_flight のコンストラクタメソッドにあります。
ステップ
属性 connection_details の定義にナビゲートし、そこから構造データ型 st_connection_details の定義に移動します。
SELECT SINGLE 命令の INTO 句で、connection_details にカーソルを置き、F3 を押します。または、Ctrl キーを押しながら connection_details をクリックすることもできます。
DATA 命令で、st_connection_details にカーソルを置き、F3 を押します。または、Ctrl キーを押しながら st_connection_details をクリックすることもできます。
構造データ型 st_connection_details を新しいプライベート構造データ型にコピーします (推奨名: st_connections_buffer)。
TYPES 命令全体 (行 END OF st_connection_details. を含む) を選択し、Ctrl + C を押します。
private セクションまで下にスクロールし、ENDCLASS 命令の上にカーソルを置き、Ctrl + V を押してコピーしたコードを挿入します。
挿入されたコードで、st_connection_details を st_connections_buffer に置き換えます。
データベーステーブル /LRN/CONNECTION のキー項目 carrier_id および connection_id を st_connections_buffer のコンポーネント一覧の先頭に追加します。
コードを以下のように調整します。
123456789
TYPES:
BEGIN OF st_connections_buffer,
carrier_id TYPE /dmo/carrier_id,
connection_id TYPE /dmo/connection_id,
airport_from_id TYPE /dmo/airport_from_id,
airport_to_id TYPE /dmo/airport_to_id,
departure_time TYPE /dmo/flight_departure_time,
arrival_time TYPE /dmo/flight_arrival_time,
END OF st_connections_buffer.
connections_buffer という名前のプライベート静的属性を、st_connections_buffer をローデータ型とする内部テーブルとして宣言します。
クラス定義の最後に、以下のコードを追加します。
1
CLASS-DATA connections_buffer TYPE TABLE OF st_connections_buffer.
クイックフィックスを使用して、クラス lcl_passenger_flight の静的コンストラクタ (クラスコンストラクタ) を生成します。
命令 CLASS lcl_passenger_flight DEFINITION まで上にスクロールします。
lcl_passenger_flight にカーソルを置き、Ctrl + 1 を押して利用可能なクイックフィックスの一覧を表示します。
一覧から Generate class constructor を選択します。
メソッド class_constructor の実装を編集します。データベーステーブル /LRN/CONNECTION から connections_buffer 属性にすべてのレコードを読み込む SELECT 文を実装します。
コードを以下のように調整します。
1234567
METHOD class_constructor.
SELECT
FROM /lrn/connection
FIELDS carrier_id, connection_id,
airport_from_id, airport_to_id, departure_time, arrival_time
INTO TABLE @connections_buffer.
ENDMETHOD.
メソッドコンストラクタの実装で、SELECT SINGLE 命令を connections_buffer への読込アクセスに置き換えます。
注記
属性 connection_details のコンポーネント数は、connections_buffer 属性の行データ型よりも少ないことに注意してください。
SELECT SINGLE 命令全体を選択し、Ctrl + < を選択して各行の前にコメント記号を追加します。
コメントされた SELECT SINGLE 命令の後に、以下のコードを追加します。
12345678910111213
connection_details = CORRESPONDING #(
connections_buffer[
carrier_id = i_carrier_id
connection_id = i_connection_id ]
).
タスク 5: コードを再チェックする
グローバルクラスを有効化してテストします。クラスをコンソールアプリとして実行します。プロファイリングを繰り返して、パフォーマンス改善を測定します。
ステップ
グローバルクラスを有効化し、コンソールアプリとして実行します。
Ctrl + F3 を押してクラスを有効化します。
F9 を押して、クラスをコンソールアプリとして実行します。
ABAP プロファイラで実行時測定を開始します。
エディタを右クリックし、Profile As→ABAP Application (Console) を選択します。
トレースパラメータダイアログボックスで、設定を変更せずに終了を選択します。
プロファイラパースペクティブに切り替え、トレース概要を分析します。
Window→Perspective→Open Perspective→Other... を選択します。ABAP Profiling を選択し、Open を選択します。
ABAP トレースビューで、ABAP プロジェクトのコンテキストメニューからリフレッシュを選択します。または、ABAP トレースビューの任意の場所にカーソルを置き、F5 を押してトレース結果の一覧を再ロードすることもできます。
最新のトレースをダブルクリックします (これはプロジェクトの最上部にあるエントリです)。
全体の実行時間および ABAP とデータベース間の配分が概要の下部セクションに表示されます。