ABAP 内部テーブル(Internal Table)のパフォーマンス検証:大量データをBINARY SEARCHで検索

  アドオンプログラム

概要

前回READ TABLEのBINARY SEARCHを使用したパフォーマンス検証を行ってみたが、実用性に乏しいサンプルコードであった為、実際に使えそうなソースコードを用い、且つ、大量のデータで検証を実施した。
データはBKPF(約50万件)、BSEG(約110万件)を使用している。

サンプルコード:通常のLoop文

処理としては、単純にBKPFとBSEGを全件取得し、BKPFを元にBSEGを参照するというプログラムだ。WHERE句が内部的にどのような検索を行っているのは不明だが、おそらく110万件の検索を50万回行っていると想定している。プログラムはとてもシンプルであるが、60分以上プログラムが終了しないロジックとなってしまう。

次に上記をBINARY SEARCHを使い、且つ、最低限の検索回数となるよう変えてみよう。

サンプルコード:BINARY SEARCH + IF文

赤字が最初のプログラムソースからの変更点となっている。
まず最初にBINARY SEARCHを使う上では必ずSORTをしておこう。テーブル上の主キーだけで検索している為、上記例ではおそらく問題ないと思うが、ショートダンプ発生の原因になりえるので、BINARY SEARCHとSORTは必ずセットで書く事をお勧めする。
次にREAD TABLEでBINARY SEARCHを行っているが、この段階で内部テーブルの値は必要ない為、TRANSPORTING NO FIELDSオプションを使い少しでもパフォーマンスを減らしている。
LOOPでは内部テーブルの検索開始位置をBINARY SEARCHを使って見つけた行のみを指定している。ポイントはWHERE句に条件を書かず、IF文でチェックしている点だ。
この例では50万件もの検索に2分もかからず検索できた。
最後にIF文で記述した条件をWHERE句にしたらどうなるのかという事を検証してみた。

サンプルコード:BINARY SEARCH + WHERE句

実行結果

対象ケース実行結果(分)
通常のLoop文2650分
BINARY SEARCH + IF文2分
BINARY SEARCH + WHERE句1470分

上記のように、想像以上の差異が発生した。
通常のLOOP文は想定通りであるが、WHERE句で指定した場合もパフォーマンスとしてはそれほど良くなかった。おそらく、インデックスの指定によって、検索対照は徐々に減っていくが、初期の検索がボトルネックになっているのだろう。
例えば、BPKFの1件目ではBSEGは150万回検索されている。BKPFの40万件目ではBSEGは30万回検索されるという風になっているのであろう。FROMだけ指定したとしてもWHERE句で条件をするだけではそれほど意味がない事が理解できる。IF文で指定した場合はBKPF1件に対してBSEGの検索はたった3回しかされない事になる。その為、これほどのパフォーマンスの差が発生したのだろう。
※BKPF1件に対して、BSEG3件という前提で記述しました。

パフォーマンスの検証としては2度程(内部テーブルのパフォーマンス向上:BINARY SEARCH有り無しの違いLOOP文の高速化(失敗))記事に掲載したが、BINARY SEARCHと IF文を組み合わせるのが最も早くできるのではないだろうか。引き続き様々な方向で検討していきたい。

LEAVE A COMMENT