1

数百万行 (おそらく 1 か月あたり最大 300 万行) を格納できる iSeries データベース テーブルに最適な SQL クエリを作成しようとしています。各行について私が持っている唯一のキーは、その RRN (行の物理レコード番号である相対レコード番号) です。

私の目標は、テーブルを別の小さなテーブルと結合して、数値列の 1 つをテキストで説明することです。ただし、関連する行数は 200 万を超える場合があり、通常、メモリ不足の状態が原因でクエリが失敗します。そのため、クエリを書き直して、大きなサブセットを他のテーブルと結合しないようにします。そのため、特定の月に 1 ページ (最大 30 行) を選択し、そのサブセットを 2 番目のテーブルに結合するという考え方です。

しかし、私は奇妙な問題に遭遇しました。次のクエリを使用して、ページに必要な行の RRN を取得します。

    select t.RRN2    -- Gives correct RRNs
    from (
      select row_number() over() as SEQ,
        rrn(e2) as RRN2, e2.*
      from TABLE1 as e2
      where e2.UPDATED between '2013-05-01' and '2013-05-31'
      order by e2.UPDATED, e2.ACCOUNT
    ) as t
    where t.SEQ > 270 and t.SEQ <= 300    -- Paging
    order by t.UPDATED, t.ACCOUNT

このクエリは問題なく機能し、必要な行の正しい RRN を返します。しかし、サブクエリの結果を別のテーブルと結合しようとすると、RRN が変更されました。そのため、結合なしで、クエリを単純な外部クエリ内のサブクエリに単純化しました。

select rrn(e) as RRN, e.*
  from TABLE1 as e
  where rrn(e) in (
    select t.RRN2    -- Gives correct RRNs
    from (
      select row_number() over() as SEQ,
        rrn(e2) as RRN2, e2.*
      from TABLE1 as e2
      where e2.UPDATED between '2013-05-01' and '2013-05-31'
      order by e2.UPDATED, e2.ACCOUNT
    ) as t
    where t.SEQ > 270 and t.SEQ <= 300    -- Paging
    order by t.UPDATED, t.ACCOUNT
  )
  order by e.UPDATED, e.ACCOUNT

外側のクエリは、RRN を行キーとして使用して、サブクエリによって選択された各行のすべての列を単純に取得します。しかし、このクエリは機能しません。まったく異なる RRN を持つ行が返されます。

後続のクエリでテーブルからより詳細な情報を取得するために使用されるため、実際の RRN が必要です。

RRN が異なる結果になる理由について何か考えはありますか?

解像度

クエリを 2 つの呼び出しに分割することにしました。1 つは単純なサブクエリを発行して RRN (行 ID) のみを返す呼び出しで、もう 1 つは残りの JOIN などを実行して各行の完全な情報を取得する呼び出しです。(テーブルは 1 日に 1 回だけ更新され、行が削除されることはないため、タイミングの問題を心配する必要はありません。)

このアプローチは非常にうまく機能しているようです。

補遺

メモリ不足エラーが発生する理由については、これは一部のテスト サーバーのみの制限のようです。約 2m 行までしか処理できないものもあれば、それ以上を処理できるものもあります。したがって、これは管理者がサーバーごとに課したある種の制限であると推測しています。

4

3 に答える 3

5

RRN を主キーとして使用しようとすると、問題が発生します。

利用可能な鍵がないとは信じがたいです。

確かに、テーブル自体に明示的な主キーが定義されていない場合があります。しかし、テーブルに一意のキーが定義されていますか?

テーブル自体にキーが定義されていない可能性があります (これは 20 年前の慣行です) が、その場合、通常、テーブルの事実上の主キーとしてアプリケーションによって定義された一意のキーを持つ論理ファイルがあります。

グリーン スクリーン (DSPDBR) または GUI (「関連の表示」を使用) を介して、関連するオブジェクトを探してみてください。キー付き論理ファイルは、GUI でビューとして表示されます。そのため、プロパティを調べて、キーのない SQL ビューではなく、一意にキーが設定された DDS 論理であるかどうかを判断する必要があります。

事実上の主キーが存在しないテーブルに何度か遭遇しました。通常、既存の列から 1 つとして定義できるものを割り出すことができました。

本当に PK がない場合は、1 つ追加するだけです。通常、生成された ID 列。従来の RPG/COBOL プログラムを再コンパイルまたはテストすることなく、列を簡単に追加するために使用できる手法があります。(LVLCHK(*NO) ではないことに注意してください!)

この手法は、近代化された Redbook http://www.redbooks.ibm.com/abstracts/sg246393.htmlの第 4 章に記載されています。

1) データを新しい PF (または SQL テーブル) に移動する 2) 既存の PF の名前を使用して新しい LF を作成する 3) 既存の LF を新しい PF (または SQL テーブル) に再ポイントする

適切に実行すると、既存のオブジェクトのレコード形式 ID は変更されないため、RPG/COBOL プログラムを再コンパイルする必要はありません。

于 2014-03-20T12:50:03.367 に答える
1

STRSQL の ALWCPYDTA(*NO) などを使用して特に制御できない場合、SQL は行の中間セットの結果行のコピーを作成する場合があります。RRN() 関数は、順序付けられた (または順序付けされていない) 行セット内の相対位置を示す論理行番号を返す ROW_NUMBER() 関数とは対照的に、常に物理レコード番号にアクセスします。コピーが生成された場合、RRN() の一貫性を保証する方法はありません。

その他の考慮事項は、時間の経過とともに適用されます。ただし、この場合は、中間結果行の単純なコピーである可能性が高くなります。

于 2014-03-20T02:03:06.980 に答える