wiki.zope.jp
PagingAndPerformance
   
RecentChanges WikiHelp WikiPractice JumpSearch

クックブック : ページングとパフォーマンスの秘密 (何度もQueryしちゃイヤん編)

2001/11 Run


ZSQLMethodは超便利です。データベースの中にあるデータを簡単にWebに引っ張り出せるのはZopeのとても良いところ。
で、でっかいテーブルとかを表示する時には、所謂「ページング」という技を使って、1画面に20件とか表示して
何処かに「次の20件」とか「前の20件」とかやるわけです。

で、Zopeでは繰り返しを行うタグである、 dtml-in に、 sizestart という属性を与えてやれば簡単にページングが出来るので、超便利。:

    <dtml-in "SQL.Employee.getAllEmployeeSQL(orderby = 'name')" size=20 start=startpos>
      <dtml-var name><br>
    </dtml-in>

とかやれば、最初から20件だけ表示してくれると。
ちなみに変数であるところの startpos が定義されていなくてもエラーにはならんです。
テスト その場合は、デフォルト値として 0 が使われるです。

次の20件とか前の20件とか表示するには、こんなコードを使うですよ。:

    <dtml-in "SQL.Employee.getAllEmployeeSQL(orderby = 'name')" previous size=20 start=startpos>
      <a href="/Employee/showAllEmployee?<dtml-var sequence-query>&startpos=<dtml-var previous-sequnece-srart-number>">
        前の<dtml-var previous-sequnece-size>件
      </a>
    </dtml-in>

    <dtml-in "SQL.Employee.getAllEmployeeSQL(orderby = 'name')" next size=20 start=startpos>
      <a href="/Employee/showAllEmployee?<dtml-var sequence-query>&startpos=<dtml-var next-sequence-start-number>">
        次の<dtml-var next-sequence-size>件
      </a>
    </dtml-in>

ここで、 sequnece-query ってのは、 /Employee/showAllEmployee を呼び出したURLに付いている引数のうち、 startpos を 除いた物が保存されている便利な変数。
あとデータの最初から表示している時には、「前のn件」は自動的に表示されない。
「次のn件」の部分も同様にデータの最後の部分を表示している時は表示されない。ううむすばらしい。

まぁ細かい部分は Zope に内蔵されている Help の中にある dtml-in の解説に譲るとして
ページングをやるときの定石は上のようになっているということで。

で、これでページングのナビゲーションと、表の表示っていう機能はちゃんと達成されているんだけれども
よく見ると同じ ZSQLMethod を3回も呼んでいます。もしやとお思いの方、正解です。

この実装方法を使うと

「本当に3回SQLクエリーが行われてしまう」

のです。超ダサダサです。パフォーマンス悪いに決まってます。

これをどう解決するか。それはZSQLMethodの戻り値を変数に一旦バインドしてしまえば全て解決!
コードは下のようになるでしょうか:

    <dtml-comment> *** データベースよりデータを得る *** </dtml-comment>
    <dtml-let result="SQL.Employee.getAllEmployeeSQL(orderby = 'name')">

      <dtml-comment> *** ナビゲーション部分 *** </dtml-comment>
      <dtml-in result previous size=20 start=startpos>
        <a href="/Employee/showAllEmployee?<dtml-var sequence-query>&startpos=<dtml-var previous-sequnece-srart-number>">
          前の<dtml-var previous-sequnece-size>件
        </a>
      </dtml-in>

      <dtml-comment> *** データ表示 *** </dtml-comment>
      <dtml-in result size=20 start=startpos>
        <dtml-var name><br>
      </dtml-in>

      <dtml-comment> *** ナビゲーション部分 *** </dtml-comment>
      <dtml-in result next size=20 start=startpos>
        <a href="/Employee/showAllEmployee?<dtml-var sequence-query>&startpos=<dtml-var next-sequence-start-number>">
          次の<dtml-var next-sequence-size>件
        </a>
      </dtml-in>
    </dtml-let>

dtml-let を使うのがミソです。これでデータベースへのQueryは1回だけになります。
この方法とは別に、対象のSQL Methodのキャッシュの設定をして、複数回のQueryを行わせないようにする技もありますが、 それだと、リアルタイムに変化し続けているようなテーブルには適用が難しいので、上の変数バインドの方法をお勧めしますですよ。


コメント

Last edited Sun, 10 Sep 2006 19:20:16 +0900 Edit this page