ABAP New open SQL:RANGEテーブルの限界について

昔から語り継がれている残念な制限に、「RANGEテーブルは1,000レコード以下を目安にすること」があると思います。

一方で、SAP HANAのドキュメントの「System Limitations」→「Length of an SQL statement」を参照すると、「2,147,483,648 Bytes」つまり、2GBとあります。
これは、単一のSQL文の文字数制限を意味しています。ちなみに、Oracleは64KBだったと思います。

話を戻して、ABAP独自のRANGEテーブルという仕組みは、Net WeaverがWhere句に展開してDatabaseに投げているそうです。CL_SHDB_SELTABというクラスもありますね。
そこで、私推測してみました。RANGEテーブルの1,000レコード制限は、Where句に展開したときに、Oracleの64KBを超えてしまう恐れがあるところから始まっているのではないだろうか?そしてSAP HANAは2GBとなっているので、100万レコードオーダーでも動くのではないだろうかと。

実際やってみました。
プログラムは以下の通りです。
・ACDOCAまたは、EKPOより、キー項目(一部)を取得して、RANGEテーブルに格納します。
・WHERE句にRANGEテーブルを設定して、結果セットを取得します。

自身が触れる環境の都合で、純粋な比較は出来ませんでしたが以下の通りになりました。

ABAP 7.31 & Oracle10.2:P-1:EKPOで測定
OK:9,998レコード
NG:9,999レコード

ABAP 7.52 & SAP HANA:P-1: EKPOで測定
OK:30,000レコード
NG:データが無いため測定不可

ABAP 7.52 & SAP HANA:P-2: ACDOCAで測定
OK:32,757レコード
NG:32.758レコード

REPORT Y_SQL_CONSOLE.

*-----------------------------------------------------------------------
* グローバル変数
*-----------------------------------------------------------------------
DATA GDF_SUBRC TYPE SY-SUBRC.

*-----------------------------------------------------------------------
* 選択画面
*-----------------------------------------------------------------------
DATA GDF_CHAR1 TYPE CHAR30.
TYPES GTR_CHAR1 LIKE RANGE OF GDF_CHAR1.
SELECT-OPTIONS S_CHAR1 FOR GDF_CHAR1.

DATA GDF_CHAR2 TYPE CHAR30.
TYPES GTR_CHAR2 LIKE RANGE OF GDF_CHAR2.
SELECT-OPTIONS S_CHAR2 FOR GDF_CHAR2.

DATA GDF_NUMC1 TYPE NUMC08.
TYPES GTR_NUMC1 LIKE RANGE OF GDF_NUMC1.
SELECT-OPTIONS S_NUMC1 FOR GDF_NUMC1.

DATA GDF_NUMC2 TYPE NUMC08.
TYPES GTR_NUMC2 LIKE RANGE OF GDF_NUMC2.
SELECT-OPTIONS S_NUMC2 FOR GDF_NUMC2.

DATA GDF_DATS1 TYPE DATS.
TYPES GTR_DATS1 LIKE RANGE OF GDF_DATS1.
SELECT-OPTIONS S_DATS1 FOR GDF_DATS1.

DATA GDF_DATS2 TYPE DATS.
TYPES GTR_DATS2 LIKE RANGE OF GDF_DATS2.
SELECT-OPTIONS S_DATS2 FOR GDF_DATS2.

DATA GDF_TIMS1 TYPE TIMS.
TYPES GTR_TIMS1 LIKE RANGE OF GDF_TIMS1.
SELECT-OPTIONS S_TIMS1 FOR GDF_TIMS1.

DATA GDF_TIMS2 TYPE TIMS.
TYPES GTR_TIMS2 LIKE RANGE OF GDF_TIMS2.
SELECT-OPTIONS S_TIMS2 FOR GDF_TIMS2.

*-----------------------------------------------------------------------
* 主処理
*-----------------------------------------------------------------------
START-OF-SELECTION.
  PERFORM START_OF_SELECTION
    USING
      S_CHAR1[]
      S_CHAR2[]
      S_NUMC1[]
      S_NUMC2[]
      S_DATS1[]
      S_DATS2[]
      S_TIMS1[]
      S_TIMS2[]
    CHANGING
      GDF_SUBRC.

*-----------------------------------------------------------------------
* サブルーチン
*-----------------------------------------------------------------------
FORM START_OF_SELECTION
    USING
      PUR_CHAR1 TYPE GTR_CHAR1
      PUR_CHAR2 TYPE GTR_CHAR2
      PUR_NUMC1 TYPE GTR_NUMC1
      PUR_NUMC2 TYPE GTR_NUMC2
      PUR_DATS1 TYPE GTR_DATS1
      PUR_DATS2 TYPE GTR_DATS2
      PUR_TIMS1 TYPE GTR_TIMS1
      PUR_TIMS2 TYPE GTR_TIMS2
    CHANGING
      POF_SUBRC TYPE SY-SUBRC.
*-----------------------------------------------------------------------
  DATA LDF_TIMESTAMP_START TYPE TIMESTAMPL.       "タイムスタンプデータ取得開始
  GET TIME STAMP FIELD LDF_TIMESTAMP_START.       "タイムスタンプデータ取得開始
*-----------------------------------------------------------------------
* Please write the SQL statement here ☆
* Set the internal table to be stored to LDT_DATA ☆
* Inline definition of LDT_DATA is fun ☆

  "P-1
  TYPES:
    BEGIN OF LTS_DATA,
      BUKRS TYPE EKPO-BUKRS,
      COUNT  TYPE I,
    END OF LTS_DATA,
    LTT_DATA TYPE STANDARD TABLE OF LTS_DATA.

  DATA:
    LDR_KEY  LIKE RANGE OF EKPO-EBELN,
    LDT_DATA TYPE LTT_DATA.
  FIELD-SYMBOLS:
    <LFS_KEY> LIKE LINE OF LDR_KEY.

  SELECT
      EKPO~EBELN AS LOW
    INTO CORRESPONDING FIELDS OF TABLE LDR_KEY
    UP TO 9998 ROWS
    FROM EKPO
    GROUP BY
      EKPO~EBELN
    ORDER BY
      EKPO~EBELN.
  LOOP AT LDR_KEY ASSIGNING <LFS_KEY>.
    <LFS_KEY>-SIGN = 'I'.
    <LFS_KEY>-OPTION = 'EQ'.
  ENDLOOP.

  TRY .
      SELECT
          EKPO~BUKRS
          COUNT( * ) AS COUNT
        INTO TABLE LDT_DATA
        FROM EKPO
        WHERE EKPO~EBELN IN LDR_KEY
        GROUP BY
          EKPO~BUKRS
        ORDER BY
          EKPO~BUKRS.
    CATCH CX_SY_OPEN_SQL_DB.


      POF_SUBRC = 8.
      RETURN.
  ENDTRY.
*
*  "P-2
*  TYPES:
*    BEGIN OF LTS_DATA,
*      RBUKRS TYPE ACDOCA-RBUKRS,
*      COUNT  TYPE I,
*    END OF LTS_DATA,
*    LTT_DATA TYPE STANDARD TABLE OF LTS_DATA.
*
*  DATA:
*    LDR_KEY  LIKE RANGE OF ACDOCA-BELNR,
*    LDT_DATA TYPE LTT_DATA.
*  FIELD-SYMBOLS:
*    <LFS_KEY> LIKE LINE OF LDR_KEY.
*
*  SELECT
*      ACDOCA~BELNR AS LOW
*    INTO CORRESPONDING FIELDS OF TABLE LDR_KEY
*    UP TO 32757 ROWS
*    FROM ACDOCA
*    GROUP BY
*      ACDOCA~BELNR
*    ORDER BY
*      ACDOCA~BELNR.
*  LOOP AT LDR_KEY ASSIGNING <LFS_KEY>.
*    <LFS_KEY>-SIGN = 'I'.
*    <LFS_KEY>-OPTION = 'EQ'.
*  ENDLOOP.
*
*  TRY .
*      SELECT
*          ACDOCA~RBUKRS
*          COUNT( * ) AS COUNT
*        INTO TABLE LDT_DATA
*        FROM ACDOCA
*        WHERE ACDOCA~BELNR IN LDR_KEY
*        GROUP BY
*          ACDOCA~RBUKRS
*        ORDER BY
*          ACDOCA~RBUKRS.
*    CATCH CX_SY_OPEN_SQL_DB.
*      POF_SUBRC = 8.
*      RETURN.
*  ENDTRY.

*-----------------------------------------------------------------------
  DATA LDF_TIMESTAMP_END TYPE TIMESTAMPL.         "タイムスタンプデータ取得終了
  GET TIME STAMP FIELD LDF_TIMESTAMP_END.         "タイムスタンプデータ取得終了
*-----------------------------------------------------------------------

  DATA:
    LDO_ALV      TYPE REF TO CL_SALV_TABLE,
    LDX_SALV_MSG TYPE REF TO CX_SALV_MSG.
  TRY.
      CL_SALV_TABLE=>FACTORY(
        IMPORTING
          R_SALV_TABLE = LDO_ALV
        CHANGING
          T_TABLE  = LDT_DATA ).
    CATCH CX_SALV_MSG INTO LDX_SALV_MSG.
      POF_SUBRC = 8.
      RETURN.
  ENDTRY.
  DATA LDO_FUNCTIONS TYPE REF TO CL_SALV_FUNCTIONS_LIST.
  LDO_FUNCTIONS = LDO_ALV->GET_FUNCTIONS( ).
  LDO_FUNCTIONS->SET_ALL( ).
  DATA LDO_SELECTIONS TYPE REF TO CL_SALV_SELECTIONS.
  LDO_SELECTIONS = LDO_ALV->GET_SELECTIONS( ).
  LDO_SELECTIONS->SET_SELECTION_MODE(
  EXPORTING
  VALUE = IF_SALV_C_SELECTION_MODE=>MULTIPLE ).

  "ヘッダ表示
  DATA LDO_HEADER TYPE REF TO CL_SALV_FORM_LAYOUT_GRID.
  CREATE OBJECT LDO_HEADER TYPE CL_SALV_FORM_LAYOUT_GRID.

  DATA LDO_H_LABEL TYPE REF TO CL_SALV_FORM_LABEL.
  LDO_H_LABEL = LDO_HEADER->CREATE_LABEL( ROW = 1 COLUMN = 1 ).
  LDO_H_LABEL->SET_TEXT( 'パフォーマンスデータ' ).

  DATA LDO_H_FLOW TYPE REF TO CL_SALV_FORM_LAYOUT_FLOW.

  LDO_H_FLOW = LDO_HEADER->CREATE_FLOW( ROW = 2  COLUMN = 1 ).
  LDO_H_FLOW->CREATE_TEXT( TEXT = 'タイムスタンプ(UTC)データ取得開始' ).
  LDO_H_FLOW = LDO_HEADER->CREATE_FLOW( ROW = 2  COLUMN = 2 ).
  DATA LDF_UTC_START TYPE CHAR30.
  WRITE LDF_TIMESTAMP_START TIME ZONE SY-ZONLO TO LDF_UTC_START.
  LDO_H_FLOW->CREATE_TEXT( TEXT = LDF_UTC_START ).

  LDO_H_FLOW = LDO_HEADER->CREATE_FLOW( ROW = 3  COLUMN = 1 ).
  LDO_H_FLOW->CREATE_TEXT( TEXT = 'タイムスタンプ(UTC)データ取得終了' ).
  LDO_H_FLOW = LDO_HEADER->CREATE_FLOW( ROW = 3  COLUMN = 2 ).
  DATA LDF_UTC_END TYPE CHAR30.
  WRITE LDF_TIMESTAMP_END TIME ZONE SY-ZONLO TO LDF_UTC_END.
  LDO_H_FLOW->CREATE_TEXT( TEXT = LDF_UTC_END ).

  LDO_H_FLOW = LDO_HEADER->CREATE_FLOW( ROW = 4  COLUMN = 1 ).
  LDO_H_FLOW->CREATE_TEXT( TEXT = 'タイムスタンプ(UTC)終了と開始の差' ).
  LDO_H_FLOW = LDO_HEADER->CREATE_FLOW( ROW = 4  COLUMN = 2 ).
  DATA LDF_TIMESTAMP_SA TYPE TIMESTAMPL.
  LDF_TIMESTAMP_SA = CL_ABAP_TSTMP=>SUBTRACT(
      TSTMP1 = LDF_TIMESTAMP_END
      TSTMP2 = LDF_TIMESTAMP_START ).
  DATA LDF_SA TYPE CHAR30.
  WRITE LDF_TIMESTAMP_SA TIME ZONE SY-ZONLO TO LDF_SA.
  LDO_H_FLOW->CREATE_TEXT( TEXT = LDF_TIMESTAMP_SA ).

  DATA LDF_COUNT TYPE INT4.
  LDO_H_FLOW = LDO_HEADER->CREATE_FLOW( ROW = 5  COLUMN = 1 ).
  LDO_H_FLOW->CREATE_TEXT( TEXT = '入力件数' ).
  LDO_H_FLOW = LDO_HEADER->CREATE_FLOW( ROW = 5  COLUMN = 2 ).
  SELECT COUNT(*) FROM EKPO INTO LDF_COUNT.
  LDO_H_FLOW->CREATE_TEXT( TEXT = LDF_COUNT ).

  LDO_H_FLOW = LDO_HEADER->CREATE_FLOW( ROW = 6  COLUMN = 1 ).
  LDO_H_FLOW->CREATE_TEXT( TEXT = '出力件数' ).
  LDO_H_FLOW = LDO_HEADER->CREATE_FLOW( ROW = 6  COLUMN = 2 ).
  DESCRIBE TABLE LDT_DATA LINES LDF_COUNT.
  LDO_H_FLOW->CREATE_TEXT( TEXT = LDF_COUNT ).

  LDO_ALV->SET_TOP_OF_LIST( LDO_HEADER ).
  LDO_ALV->SET_TOP_OF_LIST_PRINT( LDO_HEADER ).

  LDO_ALV->DISPLAY( ).

  POF_SUBRC = 0.
ENDFORM.                    "START_OF_SELECTION

検索キーワード
ABAP
ABAP 7.31
ABAP 7.4
ABAP 7.50
ABAP 7.51
ABAP 7.52
SQL
Open SQL
New Open SQL
Classic Open SQL
ABAP SQL
SAP HANA
Code to Data
Code Pushdown
SAP ERP 6.0
SAP S/4HANA
レンジテーブル
RANGE TABLE