【GeneXus Tips】レスポンス改善について <その1:ベーステーブルがある一覧>

仕事でGeneのレスポンス改善について対応する機会が増えたKudoです

今回は自分の備忘録の意味も含めてレスポンス改善で行った対応例を紹介したいと思います。

まず、WorkWithのようなベーステーブルを利用した一覧画面の表示が遅い原因は大きく分けて三つあります。

1.表示するデータ量(表示する列、行がとても多い)
2.時間のかかる処理(複雑な式を持つ項目や変数への代入処理)
3.非効率なデータベース運用(データベースのIndexが利用されていない)

実装のうえでどれも気をつけなければいけないことはわかっていても
実際にはお客様の要望を反映させようと頑張った結果、実装の必要に迫られることがあるかと思います

今回は自分が対応経験のある、2と3に係る対応をご紹介します。
結論だけいうと
式・条件の最適化
ということになります。

最適化のために確認するのは次の点になります。
・式やプロシージャー内の処理で、遅い処理が先に呼ばれている
> 早い処理を先に持ってくることで遅い処理を行わないで済む
・”ForEach”を”Return”で抜けている
> Returnで抜けると、DBのカーソルが解放されないものがあるため(Oracle等)、DB全体のレスポンスが下がる
Exitで抜けることで抜ける方法が正しい
・簡単な処理をプロシージャで行っている
> Find式や単純な式にすることでアプリケーションサーバーの処理からDBサーバーの処理になる場合がある
・Where句や式の条件にIsEmptyやIsNullを使用している
> IsEmptyやIsNullを利用すると、Indexが利用されなくなる
・Where句や式の条件に否定条件を利用している
> 否定式のままSQLになる→多くのDBでは否定の条件でIndexが利用されない
・Where句や式の条件に関数を利用している
> データベースや関数にもよるが、SQLに置き換えられず、アプリケーション側の処理になる場合がある
・Where句や式の条件の左辺が式になっている
> そのままSQLになるため、Indexが利用されなくなる
・Where句や式の条件の左辺が式項目になっている
> SQLレベルでは処理されず、アプリケーション側で再度取得したデータから絞り込むため遅くなる
特に
・”ForEach”を”Return”で抜けている
は危険です、サーバー全体に影響が出てしまいます。
そして、よくやってしまうのが
・簡単な処理をプロシージャで行っている
・Where句や式の条件にIsEmptyやIsNullを使用している
・Where句や式の条件に否定条件を利用している
・Where句や式の条件の左辺が式項目になっている
です。

  ”同一処理の一元管理”
  ”空以外、○○以外といった条件のわかりやすい実装”
どれもコーディングにおいては正しい対応ではありますが
GeneXusにおいては、記述したコードが生成されるSQLへ影響するため
コードの非正規化も考慮する必要があります。

たとえば以下のようなトランザクションがあった場合

式項目の「DeleteState」の式は次の様に置き換えることで削除日にIndexがある場合に限り、評価を高速化できる可能性があります。

また、このような項目をFor Eachの条件で利用した場合

次の様に書き直すことで、最適なSQLをジェネレートさせることができます

しかし、いくら最適化を行ってもどうしようもない処理(大量データの集計等)もあります。
そういった項目は、予め計算した値を格納しておく、つまり実態を持つように設計することがあります。
GeneXusではこのような対応を行う場合”冗長化”というプロパティを使うことである程度手軽に実装することができます。

トランザクションのStructureに”冗長”の項目が表示されていなければ次の方法で表示させます。
1.Structureの項目名で右クリックしてメニューを表示、”表示列の選択”をクリックします。

2.”表示列の選択”というウィンドウが表示されるので、ここにある”冗長”という項目をStructureの項目名のところまでドラッグします。

3.項目に”冗長”が追加されると式項目にチェックボックスが表示されます。
このチェックボックスにチェックを入れることで、冗長化の設定は完了です。

注意点としては、冗長化を行った項目を持ったトランザクションを利用した処理、
たとえば、トランザクション画面を利用したアップデートやBC(ビジネスコンポーネント)の場合しか冗長化項目の更新処理は実行されません。
ほか処理でこの項目を変更する場合は、別途更新処理を記述する必要があります。

次はSDTを利用した一覧の場合を書きたいと思います(時期未定)