28
Rendimiento en la programación ABAP Contenido [ocultar ] 1 Introducción 2 Interfaz SQL o 2.1 Select ... Where vs. Select + Check o 2.2 Select single vs. Select-Endselect o 2.3 Funciones agregadas o 2.4 Select con Vistas o 2.5 Select con soporte de buffer o 2.6 Actualización de columnas o 2.7 Select con soporte de índices o 2.8 Select ... Into Table t o 2.9 Select-Endselect vs. Array-Select. o 2.10 Select with select list o 2.11 Arrar Insert vs. Single-row Insert 3 Manipulación de strings o 3.1 Operadores especiales en IF (CA,...) o 3.2 Concatenación de strings o 3.3 Borrando espacios en blanco o 3.4 Concatenación de strings o 3.5 Particiones de strings o 3.6 Longitud de strings 4 Tablas internas o 4.1 Generando tablas ordenadas o 4.2 Generando tablas sin duplicados o 4.3 Diferentes formas de acceso con clave o 4.4 Clave de acceso para múltiple líneas o 4.5 Copiando tablas internas o 4.6 Ordenando tablas internas o 4.7 Loops Anidados o 4.8 Borrando una secuencia de líneas

Rendimiento en la programación ABAP

Embed Size (px)

Citation preview

Page 1: Rendimiento en la programación ABAP

Rendimiento en la programación ABAPContenido

 [ocultar]

1 Introducción

2 Interfaz SQL

o 2.1 Select ... Where vs. Select + Check

o 2.2 Select single vs. Select-Endselect

o 2.3 Funciones agregadas

o 2.4 Select con Vistas

o 2.5 Select con soporte de buffer

o 2.6 Actualización de columnas

o 2.7 Select con soporte de índices

o 2.8 Select ... Into Table t

o 2.9 Select-Endselect vs. Array-Select.

o 2.10 Select with select list

o 2.11 Arrar Insert vs. Single-row Insert

3 Manipulación de strings

o 3.1 Operadores especiales en IF (CA,...)

o 3.2 Concatenación de strings

o 3.3 Borrando espacios en blanco

o 3.4 Concatenación de strings

o 3.5 Particiones de strings

o 3.6 Longitud de strings

4 Tablas internas

o 4.1 Generando tablas ordenadas

o 4.2 Generando tablas sin duplicados

o 4.3 Diferentes formas de acceso con clave

o 4.4 Clave de acceso para múltiple líneas

o 4.5 Copiando tablas internas

o 4.6 Ordenando tablas internas

o 4.7 Loops Anidados

o 4.8 Borrando una secuencia de líneas

o 4.9 Generando tablas condensadas

Page 2: Rendimiento en la programación ABAP

o 4.10 Búsqueda Lineal vs. Binaria

o 4.11 Índices secundarios

o 4.12 Usando un área explícita de trabajo

o 4.13 Comparando tablas internas

o 4.14 Uniendo tablas internas

o 4.15 Borrando duplicados

o 4.16 Borrando un conjunto de líneas

o 4.17 WorkAreas vs Field-Symbols

5 Tipos de datos

o 5.1 Tipos de datos declarados vs. parámetros sin declaración de tipo.

o 5.2 Declaración de tipos vs. sin declaración de tipos en Field-symbols

o 5.3 If vs. Case

o 5.4 Case vs. Perform I of …

o 5.5 While vs. Do

6 Conversión de Campos

o 6.1 Campos tipos I y P

o 6.2 Constantes tipo F

o 6.3 Mezcla de tipos

o 6.4 Literales tipo C y tipo I

o 6.5 Aritmética

7 UTILIZACIÓN DE TABLAS TRANSPARENTES, POOL Y CLUSTERS

o 7.1 Tablas Transparentes y Pool

o 7.2 Tablas Cluster

o 7.3 Atributos de los campos en el WHERE

8 Generación de índices secundarios

9 Enlaces

Introducción

• Este documento es una compilación de distintas sentencias y procedimientos de programación en

ABAP/4 relacionados con performance. Estas sentencias y procedimientos son comparados para

determinar cuales tienen mejor performance. Los tiempos medidos para la ejecución no deben tomarse

como valores absolutos sino como valores indicatiovos de comparación de performance. No pueden

tomarse como valores de ejecución para una instalación determinada ya que fueron medidos en una

server específico, con una carga de trabajo despreciable.

Page 3: Rendimiento en la programación ABAP

• Además de las consideraciones sobre sentencias y procedimientos ABAP/4 se desarrollan puntos a

tener en cuenta relacionados con la base de datos de SAP (vistas, índices, etc.).

Interfaz SQL

Select ... Where vs. Select + Check

Select + Check Select sin condición

SELECT * FROM VERI_CLNTCHECK: VERI_CLNT-ARG1 = ’7’.ENDSELECT.

SELECT * FROM VERI_CLNTWHERE ARG1 = ’7’.ENDSELECT.

88,234 microsegundos 4,907 microsegundos

• Siempre especifique sus condiciones en la cláusula WHERE en vez de realizar la evaluación de la

condición con la instrucción check.

• La base de datos entonces puede usar un índice ( si existe alguno adecuado ) siendo la performance

de la red considerablemente mejor.

Select single vs. Select-Endselect

Select ... Endselect Select single * ...

SELECT * FROM VERI_CLNTWHERE ARG1 = ’7’ ANDARG2 = ’ ’.ENDSELECT.

SELECT SINGLE * FROM VERI_CLNTWHERE ARG1 = ’7’ AND ARG2 = ’ ’.

4,549 microsegundos 4,160 microsegundos

• Si necesita una sola fila de una tabla de base de datos o vista, use la instrucción SELECT SINGLE en

vez de un loop SELECT-ENDSELECT.

• SELECT SINGLE requiere una comunicación (I/O) con el sistema de la base de datos, mientras que

SELECT-ENDSELECT necesita dos.

Funciones agregadas

Select ... Where + Check Select using una función agregada

C4A = ’000’.SELECT * FROM T100WHERE SPRSL = ’000’.CHECK: T100-MSGNR > C4A.C4A = T100-MSGNR.ENDSELECT.

SELECT MAX(MSGNR) FROM T100 INTO C4AWHERE SPRSL = ’D’ ANDARBGB = ’00’.

221,213 microsegundos 24,470 microsegundos

• Si requiere encontrar el valor máximo, mínimo, sumatoria y promedio o la cantidad de una columna de

la base de datos; use las funciones agregadas en vez de agregar instrucciones para realizar el cálculo.

Page 4: Rendimiento en la programación ABAP

Select con Vistas

Instrucciones Select anidadas Select con vistas

SELECT * FROM DD01LWHERE DOMNAME LIKE ’CHAR%’ ANDAS4LOCAL = ’A’.SELECT SINGLE * FROM DD01T WHEREDOMNAME = DD01L-DOMNAME ANDAS4LOCAL = ’A’ ANDAS4SERVERS = DD01L-AS4VERS ANDDDLANGUAJE = SY-LANGU.ENDSELECT.

SELECT * FROM DD01VWHERE DOMNAME LIKE ’CHAR%’ ANDDDLANGUAJE = SY-LANGU.ENDSELECT.

1,472,996 microsegundos 308,670 microsegundos

• Para procesar un join, use una vista en vez de instrucciones Select anidadas.

Select con soporte de buffer

Select sin soporte de buffer Select con soporte de buffer

SELECT SINGLE * FROM T100BYPASSING BUFFERWHERE SPRSL = ’D’ ANDARBGB = ’00’ ANDMSGNR = ’999’.

SELECT SINGLE * FROM T100WHERE SPRSL = ’D’ ANDARBGB = ’00’ ANDMSGNR = ’999’.

4,395 microsegundos 242 microsegundos

• Para tablas de solo lectura y uso frecuente, utilice SAP buffering.

Actualización de columnas

Actualización de una línea por vez Actualización de las columnas

SELECT * FROM VERI_CLNT.VERI_CLNT-FUNCTINT =VERI_CLNT-FUNCTNT + 1.UPDATE VERI_CLNT.ENDSELECT.

UPDATE VERI_CLNTSET FUNCTINT = FUNCTINT + 1.

545,008 microsegundos 70,487 microsegundos

• Siempre que sea posible utilice la actualización por columnas, en vez de actualizar una línea de la

tabla de la base de datos.

Select con soporte de índices

Select sin soporte de índices Select con soporte de índices

Page 5: Rendimiento en la programación ABAP

SELECT * FROM T100WHERE ARBGB = ’00’ ANDMSGNR = ’999’.ENDSELECT.

SELECT * FROM T002.SELECT * FROM T100WHERE SPRSL = T002-SPRAS ANDARBGB = ’00’ ANDMSGNR = ’999’.ENDSELECT.ENDSELECT.

3,749,142 microsegundos 121,096 microsegundos

• Para todo uso frecuente de la instrucción Select, trate de utilizar un índice. Siempre se usa un índice si

se especifica una parte genérica de lo/s campos del índice, concatenándolos con AND lógicos en la

cláusula WHERE.

Select ... Into Table t

Select + instrucción Append Select into table

REFRESH X006.SELECT * FROM T006 INTO TABLE X006.APPEND X006.ENDSELECT.

SELECT * FROM T006 INTO TABLE X006.

2,246 microsegundos 829 microsegundos

• Es siempre más rápido usar la instrucción Select into table que usar la instrucción Append.

Select-Endselect vs. Array-Select.

Select into Table t ... Loop at t Select ... Endselect.

SELECT * FROM T006 INTO TABLE X006.LOOP AT TABLE X006.ENDLOOP.

SELECT * FROM T006.ENDSELECT.

1,117 microsegundos 2,022 microsegundos

• Si procesa sus datos sólo una vez , use un SELECT-ENDSELECT-LOOP en vez de guardar los datos

en una tabla interna con SELECT INTO TABLE. El manejo de una tabla interna consume más espacio.

Select with select list

Select * Select .with select list

SELECT * FROM DD01L WHEREDOMNAME LIKE ’CHAR%’ ANDAS4LOCAL = ’A’.ENDSELECT.

SELECT DOMNAME FROM DD01LINTO DD01L-DOMNAME WHEREDOMNAME LIKE ’CHAR%’ ANDAS4LOCAL = ’A’.ENDSELECT.

Page 6: Rendimiento en la programación ABAP

240,062 microsegundos 89,276 microsegundos

• Si sólo le interesan determinadas columnas de la tabla,use una lista de campos o una vista en vez de

SELECT * .

Arrar Insert vs. Single-row Insert

Inserción de una línea por vez. Inserción con arreglos

* Tabla TAB con 100 entradasLOOP AT TAB.INSERT INTO VERI_CLNT VALUES TAB.ENDLOOP.

* Tabla TAB con 100 entradasINSERT VERI_CLNT FROM TABLE TAB.

463,581 microsegundos 53,917 microsegundos

• Siempre que sea posible, utilice operaciones con arreglos, en vez de operaciones sobre una fila.

• La frecuente comunicación entre el programa de aplicación y el sistema de la base de datos produce

un considerable overhead.

Manipulación de strings

Operadores especiales en IF (CA,...)

Do-Loop con Field-Symbols Usando el operador CA

ASSIGN CHA(1) TO <C>.DO 200 TIMES.IF <C> = ’(’ OR <C> = ’)’." Alguna operación.EXIT.ENDIF.ASSIGN <C>+1 TO <C>.ENDDO.

IF CHA(200) CA ’()’." Alguna operación.ENDIF.

1,123 microsegundos 443 microsegundos

• Utilice los operadores especiales CO, CA, CS en vez de adicionar instrucciones de programación.

• Si se ejecutan instrucciones ABAP por cada caracter de un string, el consumo de CPU puede

incrementarse substancialmente.

Concatenación de strings

Moviendo con offset Usando la instrucción CONCATENATE

MOVE ’Jane’ TO CMA.MOVE ’Miller’ TO CMB.MOVE ’New York City’ TO CMC.I1 = STRLEN(CMA). I2 = STRLEN(CMB).

MOVE ’Jane’ TO CMA.MOVE ’Miller’ TO CMB.MOVE ’New York City’ TO CMC.

Page 7: Rendimiento en la programación ABAP

MOVE ’Mrs.’ TO CHA.MOVE CMA TO CHA+5. I1 = I1 + 6.MOVE CMB TO CHA+I1. I1 = I1 + 12 + 1.MOVE ’from’ TO CHA+I1. I1 = I1 + 11 + 5.MOVE CMC TO CHA+I1.

"Mrs. Jane Miller from New York City" es el valorfinal de CHA.

CONCATENATE’Mrs.’ CMA CMB ’from’ CMC INTO CHA SEPARATEBY SPACE.

"Mrs. Jane Miller from New York City" es el valorfinal de CHA.

93 microsegundos 28 microsegundos

• Utilice la instrucción CONCATENATE en vez de adicionar instrucciones de programación.

Borrando espacios en blanco

Corriendo SY-FDPOS lugares Usando SHIFT ... LEFT DELETING LEADING

" CLA contiene el string" ’ " Editor line n".

IF CLA CN SPACE. ENDIF.SHIFT CLA BY SY-FDPOS PLACES LEFT

" CLA contiene el string" ’ " Editor line n".

SHIFT CLA LEFT DELETING LEADING SPACE.

100 microsegundos 8 microsegundos

• Si quiere borrar los espacios en un string, utilice la instrucción SHIFT ... LEFT DELETING LEADING ...

• Otras instrucciones no tan rápidas:

• CN y SHIFT ... BY SY-FDPOS PLACES, con CONDENSE si es posible.

• CN y ASSIGN CLA+SY-FDPOS(LEN) ...

• Evite usar SHIFT dentro de un loop WHILE.

Concatenación de strings

Usando una función para concatenar Usando la instrucción CONCATENATE

CALL FUNCTION ’STRING_CONCATENATE_3’EXPORTINGSTRING1 = T100-ARBGBSTRING2 = T100-MSGNRSTRING3 = T100-TEXTIMPORTINGSTRING = CLAEXCEPTIONSTOO_SMALL = 01.

CONCATENATE T100-ARBGBT100-MSGNRT100-TEXT INTO CLA.

194 microsegundos 14 microsegundos

• Algunas funciones para el manejo de strings tienden a ser obsoletas y fueron reemplazadas por otras

instrucciones o funciones en ABAP/4.

Page 8: Rendimiento en la programación ABAP

• STRING_CONCATENATE  CONCATENATE

• STRING_SPLIT  SPLIT

• STRING_LENGTH  STRLEN()

• STRING_CENTERED  WRITE ... TO ... CENTERED

• STRING_MOVE_RIGHT  WRITE ... TO ... RIGHT-JUSTIFIED

Particiones de strings

Uso de SEARCH y MOVE con offset Uso de la instrucción SPLIT

CMA contiene ’(410)-45174-6654312’ y será divididoen Código de Area, Teléfono1 y Teléfono2

SEARCH CMA FOR ’-’.MOVE CMA(SY-FDPOS) TO AREA_CODE.I1 = SY-FDPOS + 2.

SEARCH CMA FOR ’-’ STARTING AT I1.I1 = I1 - 1.MOVE CMA+I1(SY-FDPOS) TO TEL_NO1.I1 = I1 + SY-FDPOS + 1.MOVE CMA+I1 TO TEL_NO2.

CMA contiene ’(410)-45174-6654312’ y será divididoen Código de Area, Teléfono1 y Teléfono2

SPLIT CMA AT ’-’ INTO AREA_CODETEL_NO1TEL_NO2.

66 microsegundos 11 microsegundos

• Utilice la instrucción SPLIT en vez de realizar una programación para dividir un string.

Longitud de strings

Obtener el CHECK_SUM con la longitud del campo Obtener el CHECK_SUM con strlen()

DATA: BEGIN OF STR,LINE TYPE X, ENDOF STR,CHECK_SUM TYPE I.MOVE ’KALEBVPQDSCFG’ TO CLA.

DO 64 TIMES VAYING STR FROM CLANEXT CLA+1.CHECK STR NE SPACE.ADD STR-LINE TO CHECK_SUM.

ENDDO.

DATA: BEGIN OF STR,LINE TYPE X, ENDOF STR,CHECK_SUM TYPE I.MOVE ’KALEBVPQDSCFG’ TO CLA.

I1 = STRLEN(CLA).DO I1 TIME VARYING STR FROM CLA NEXTCLA+1.CHECK STR NE SPACE.ADD STR-LINE TO CHECK_SUMENDDO.

597 microsegundos 171 microsegundos

• Utilice la función STRLEN() para restringir la cantidad de ciclos que debe efectuar la instrucción DO,

cuando determina un CHECK_SUM.

Tablas internas

Page 9: Rendimiento en la programación ABAP

Generando tablas ordenadas

Generación en un paso usando read/insert Generación en dos pasos usando append y luego sort

TAB_DES contiene 1000 entradas

REFRESH TAB_DEST.LOOP AT TAB_SRC.READ TABLE TAB_DEST WITH KEYK = TAB_SRC-K BINARY SEARCH.INSERT TAB_SRC INTO TAB_DEST INDEXSY-TABIX.ENDLOOP.

TAB_DES contiene 1000 entradas

REFRESH TAB_DEST.LOOP AT TAB_SRC.APPEND TAB_SRC TO TAB_DEST.ENDLOOP.

SORT TAB_DEST BY K.

98,545 microsegundos 20,693 microsegundos

• Si la cantidad de líneas es pequeña, (menor a 20 entradas), o si se necesita acceder a la tabla interna

mientras ésta es llenada; usar la opción READ/INSERT es la correcta.

• Si la cantidad de datos es grande y la tabla se usará sólo una vez que este llena, es preferible el

proceso en dos pasos.

Generando tablas sin duplicados

Generación en un paso Generación en tres pasos

TAB_DES contiene 1000 entradas de las cuales 500son diferentes

REFRESH TAB_DEST.LOOP AT TAB_SRC.READ TABLE TAB_DEST WITH KEYK = TAB_SRC-K BINARY SEARCH.IF SY-SUBRC <> 0.INSERT TAB_SRC INTO TAB_DEST INDEXSY-TABIX.ENDIF.ENDLOOP.

TAB_DES contiene 1000 entradas de las cuales 500son diferentes

REFRESH TAB_DEST.LOOP AT TAB_SRC.APPEND TAB_SRC TO TAB_DEST.ENDLOOP.

SORT TAB_DEST BY K.DELETE ADJACENT DUPLICATES FROMTAB_DEST COMPARING K.

43,469 microsegundos 26,259 microsegundos

• Si la cantidad de líneas es pequeña, (menor a 20 entradas), o si se necesita acceder a la tabla interna

mientras ésta es llenada; usar la opción READ/INSERT es la correcta.

• Si la cantidad de datos es grande y la tabla se usará sólo una vez que este llena, es preferible el

proceso en tres pasos.

Diferentes formas de acceso con clave

Acceso vía una clave default implícita Acceso vía una clave explícitamente asignada

Page 10: Rendimiento en la programación ABAP

Tabla TAB contiene 30 entradas de 500 bytes cada.La instrucción READ finaliza con SY-SUBRC=4

MOVE SPACE TO TAB.TAB-K = ’X’.READ TABLE TAB BINARY SEARCH.

Tabla TAB contiene 30 entradas de 500 bytes cada.La instrucción READ finaliza con SY-SUBRC=4

READ TABLE TAB WITH KEYK = ’X’ BINARY SEARCH.

37 microsegundos 15 microsegundos

• Si es posible, especifique el campo clave para realizar la lectura. De otra manera el campo clave tiene

que ser calculado dinámicamente por el runtime system.

Clave de acceso para múltiple líneas

Clave de acceso con LOOP/CHECK Clave de acceso con LOOP … WHERE

Tabla TAB contiene 100 entradas de 500 bytes cada una, solo 5 coinciden con la clave de búsqueda.

LOOP AT TAB.CHECK TAB-K = KVAL." ...ENDLOOP.

Tabla TAB contiene 100 entradas de 500 bytes cada una, solo 5 coinciden con la clave de búsqueda.

LOOP AT TAB WHERE K = KVAL." ...ENDLOOP.

1,395 microsegundos 387 microsegundos

• LOOP … WHERE es más rápido que LOOP/CHECK porque LOOP … WHERE evalúa la condición

específica internamente.

• Como todas las expresiónes lógicas, la performance es mejor si los operandos son del mismo tipo de

datos. La performance puede ser incrementada si el LOOP … WHERE es combinado con FROM i1

and/or TO i2, si es posible.

Copiando tablas internas

Forma rudimentaria para copiar una tabla interna

Tabla TAB_SRC contiene 100 entradas de 100Bytes cada.

REFRESH TAB_DEST.LOOP AT TAB_SRC INTO TAB_DEST.APPEND TAB_DEST.ENDLOOP.

Tabla TAB_SRC contiene 100 entradas de 100 Bytes cada.

TAB_DEST[] = TAB_SRC[].

949 microsegundos 314 microsegundos

Page 11: Rendimiento en la programación ABAP

• Las tablas internas pueden ser copiadas por asignación igual que cualquier otro tipo de objetos de

datos. Si la tabla interna itab tiene una línea de cabecera, la tabla puede accederse por itab[ ]

Ordenando tablas internas

SORT itab con una clave de ordenamiento por default

SORT itab con una clave específica

Tabla TAB contiene 100 entradas de 500 bytes cada una

SORT TAB.

Tabla TAB contiene 100 entradas de 500 bytes cada una

SORT TAB BY K.

2,026 microsegundos 821 microsegundos

• La ejecución sera más rápida si se especifica la mayor cantidad posible de claves de ordenamiento.

Loops Anidados

Loops anidados Loop de cursor paralelo

Tabla TAB1 contiene 100 entradas de 100 bytes cada unaTabla TAB2 contiene 10 * 100 = 1000 entradas de 100 bytes cada una

LOOP AT TAB1.LOOP AT TAB2 WHERE K = TAB1-K." ...ENDLOOP.ENDLOOP.

Tabla TAB1 contiene 100 entradas de 100 bytes cada unaTabla TAB2 contiene 10 * 100 = 1000 entradas de 100 bytes cada una

I2 = 1.LOOP AT TAB1.LOOP AT TAB2 FROM I2.IF TAB2-K <> TAB1-K.I2 = SY-TABIX.EXIT.ENDIF." ...ENDLOOP.ENDLOOP.

394,175 microsegundos 10,029 microsegundos

• Si TAB1 tiene n1 entradas y TAB2 tiene n2 entradas, el tiempo necesario para el loop anidado con el

algoritmo directo es O(n1 * n2), cuando el cursor paralelo toma sólo O(n1 + n2). El algoritmo de cursor

paralelo asume que TAB2 contiene sólo las entradas que también contiene en TAB1.

• Si esto no es cierto, el algoritmo de cursor paralelo se torna ligeramente más complicado, pero su

característica de performance es la misma.

Borrando una secuencia de líneas

Rudimentaria forma para borrar una secuencia de Ordenando al kernel a realizar el trabajo

Page 12: Rendimiento en la programación ABAP

líneas

Tabla TAB_DEST contiene 1000 entradas 500 bytes cada una, las líneas 450 a 550 serán borradas.

DO 101 TIMES.DELETE TAB_DEST INDEX 450.ENDDO.

Tabla TAB_DEST contiene 1000 entradas 500 bytes cada una, las líneas 450 a 550 serán borradas.

DELETE TAB_DEST FROM 450 TO 550.

3,119 microsegundos 128 microsegundos

• Con la nueva variante del delete

DELETE itab FROM … TO …

la tarea de borrar una secuencia de líneas puede ser transferidas al kernel.

Generando tablas condensadas

COLLECT usando semántico READ BINARY Juntando vía COLLECT

Tabla TAB_SRC contiene 10,000 entradas, 5,000de las cuales tiene diferente claves

LOOP AT TAB_SRC.READ TABLE TAB_DEST WITH KEYK = TAB_SRC-K BINARY SEARCH.IF SY-SUBRC = 0.ADD: TAB_SRC-VAL1 TOTAB_DEST-VAL1,TAB_SRC-VAL2 TOTAB_DEST-VAL2MODIFY TAB_DEST INDEX SY-TABIX.ELSE.INSERT TAB_SRC INTO TAB_DESTINDEX SY-TABIX.ENDIF.ENDLOOP.

Tabla TAB_SRC contiene 10,000 entradas, 5,000de las cuales tiene diferente claves

LOOP AT TAB_SRC.COLLECT TAB_SRC INTO TAB_DEST.ENDLOOP.SORT TAB_DEST BY K.

1,580,904 microsegundos 284,471 microsegundos

• Si necesita la semántica del COLLECT , use COLLECT!

• READ BINARY ejecuta en O(LOG2(n)) tiempo, y el índice de la tabla interna debe ser ajustado con

cada INSERT. COLLECT, sin embargo, usa un algoritmo hash y es independiente del número de

entradas i.e. O(1) y no necesita mantener una tabla de índices. Si necesita al final los datos ordenados,

ordénelos después de que los datos han sido coleccionados.

• Si la cantidad de datos es pequeña, el acercamiento READ/INSERT no es malo, pero para cantidades

mayores de datos (>1000), COLLECT es mucho más rápido.

Page 13: Rendimiento en la programación ABAP

• CUIDADO: cuando carga una tabla interna, no utilice COLLECT en combinación con alguna instrucción

de carga de tablas, por ejemplo (APPEND, INSERT, and/or MODIFY). Si mezcla COLLECT con otra

instrucción, COLLECT no puede usar su algoritmo hash. En este caso COLLECTS ejecuta una

búsqueda lineal, la cual es dramaticamente lenta: O(n).

Búsqueda Lineal vs. Binaria

Búsqueda Lineal Búsqueda Binaria

Tabla TAB contiene 1000 entradas de 100 bytescada. El READ finaliza con SY-SUBRC=4

READ TABLE TAB WITH KEY K = ’X’.

Tabla TAB contiene 1000 entradas de 100 bytescada. El READ finaliza con SY-SUBRC=4

READ TABLE TAB WITH KEYK = ’X’ BINARY SEARCH.

1,452 microsegundos 29 microsegundos

• Si la tabla interna tiene muchas (>20) entradas, en una búsqueda lineal a través de todas las entradas

el tiempo consumido es bastante alto. Trate de mantener la tabla ordenada y usar búsqueda binaria.

• Si TAB tiene n entradas, la búsqueda lineal se ejecuta en O(n) de tiempo, mientras que la búsqueda

binaria toma solamente O(log2(n)) de tiempo.

Índices secundarios

Sin índice secundario búsqueda lineal Búsqueda binaria usando índice secundario

Tabla TAB contiene 1000 entradas. El READ usa las 500 primeras entradas.

READ TABLE TAB WITH KEYDATE = SY-DATUM.IF SY-SUBRC = 0....ENDIF.

Tabla TAB contiene 1000 entradas. El READ usa las 500 primeras entradas.

READ TABLE TAB_INDEX WITH KEYDATE = SY-DATUM BINARY SEARCH.IF SY-SUBRC = 0.READ TABLE TAB INDEXTAB_INDEX-INDX....ENDIF.

798 microsegundos 32 microsegundos

• Si se necesita acceder a una tabla con diferentes claves repetidamente, mantenga su propio índice

secundario.

• Con un índice secundario, puede remplazar una búsqueda lineal con una búsqueda binaria más un

acceso indexado .

Usando un área explícita de trabajo

Operaciones con tablas vía la línea de cabecera Operaciones con tablas vía una explícita área de trabajo

Page 14: Rendimiento en la programación ABAP

El ancho de la línea de la tabla TAB es 500 bytes

TAB = TAB_WA.APPEND TAB.

El ancho de la línea de la tabla TAB es 500 bytes

APPEND TAB_WA TO TAB.

17 microsegundos 9 microsegundos

• Evite los MOVEs innecesarios, usando las operaciones explícitas de áreas de trabajo.

• APPEND wa TO tab

• INSERT wa INTO tab

• COLLECT wa INTO tab

• MODIFY tab FROM wa

• READ tab INTO wa

• LOOP AT tab INTO wa cuando es apropiado.

Comparando tablas internas

Rudimentaria forma para comparar tablas internas Ordenando al kernel a realizar el trabajo

Tablas TAB1 y TAB2 tienen cada 100 entradas de 100 Bytes cada

DESCRIBE TABLE: TAB1 LINES L1,TAB2 LINES L2.IF L1 <> L2.TAB_DIFFERENT = ’X’.ELSE.TAB_DIFFERENT = SPACELOOP AT TAB1.READ TABLE TAB2 INDEX SY-TABIX.IF TAB1 <> TAB2.TAB_DIFFERENT = ’X’. EXIT.ENDIF.ENDLOOP.ENDIF.IF TAB_DIFFERENT = SPACE." ...ENDIF.

Tablas TAB1 y TAB2 tienen cada 100 entradas de 100 Bytes cada

IF TAB1[] = TAB2[]." ...ENDIF.

1,774 microsegundos 535 microsegundos

• Una tabla interna puede ser comparada en una expresión lógica igual que otros objetos.

• Dos tablas internas son iguales si tienen el mismo numero de líneas y cada par de correspondiente

línea es igual.

• Si una tabla interna itab tiene la línea de cabecera, la tabla en si misma es accedida por itab[].

Page 15: Rendimiento en la programación ABAP

Uniendo tablas internas

Join natural: loop tab1, read tab2 con clave Cursor paralelo

Tabla TAB1 contiene 1000 entradas de 100 bytes cada una.Tabla TAB2 contiene 300 entradas de 100 bytes cada una.Tabla TAB2 se asume ordenada por K en orden ascendente

LOOP AT TAB1.READ TABLE TAB2 WITH KEYK = TAB1-K BINARY SEARCH.IF SY-SUBRC = 0....ENDIF.ENDLOOP.

Tabla TAB1 contiene 1000 entradas de 100 bytes cada una.Tabla TAB2 contiene 300 entradas de 100 bytes cada una.Tabla TAB2 se asume ordenada por K enorden ascendente

I2 = 1.LOOP AT TAB1.READ TABLE TAB2 INDEX I2.IF SY-SUBRC <> 0. EXIT. ENDIF.IF TAB2-K = TAB1-K." ...ADD 1 TO I2.ENDIF.ENDLOOP.

28,319 microsegundos 9,824 microsegundos

• Si TAB1 tiene n1 entradas y TAB2 tiene n2 entradas, el tiempo necesario para juntar TAB1 y TAB2 con

el algoritmo directo es O(n1 * log2(n2)), mientras un acercamiento de cursor paralelo toma solamente

O(n1 + n2) de tiempo.

• El mencionado algoritmo de cursor paralelo asume que TAB2 es un tabla secundaria conteniendo solo

entradas también contenidas en la tabla primaria TAB1. Si esta asunción no es verdadera, el algoritmo

de cursor paralelo es ligeramente más complicado, pero su performance restante es la misma.

Borrando duplicados

Rudimentaria forma de borrar duplicados Ordenado al kernel a realizar el trabajo

Tabla TAB_DEST contiene 1000 entradas de 100 bytes cada y contiene 500 pares de duplicados

READ TABLE TAB_DEST INDEX 1 INTO PREV_LINE.LOOP AT TAB_DEST FROM 2.IF TAB_DEST = PREV_LINE.DELETE TAB_DEST.ELSE.PREV_LINE = TAB_DEST.ENDIF.ENDLOOP.

Tabla TAB_DEST contiene 1000 entradas de 100 bytes cada y contiene 500 pares de duplicados

DELETE ADJACENT DUPLICATES FROM TAB_DEST COMPARING K.

26,826 microsegundos 4,159 microsegundos

• Con la nueva variante del DELETE , DELETE ADJACENT DUPLICATES, la tarea del borrado es

transferida al kernel.

Page 16: Rendimiento en la programación ABAP

Borrando un conjunto de líneas

Rudimentaria forma de borrar un conjunto de líneas Ordenado al kernel a realizar el trabajo

Tabla TAB_DEST contiene 1000 entradas de 500bytes cada, estas coinciden el WHERE condition

LOOP AT TAB_DEST WHERE K = KVAL.DELETE TAB_DEST.ENDLOOP.

Tabla TAB_DEST contiene 1000 entradas de 500bytes cada, estas coinciden el WHERE condition

DELETE TAB_DEST WHERE K = KVAL.

14,491 microsegundos 6,496 microsegundos

• Con la nueva variante del delete, DELETE itab [FROM … ] [TO … ] WHERE … , la tarea de borrar un

conjunto de líneas puede ser transferido al kernel. Si es posible, WHERE debería ser usado junto con

FROM … and/or TO para mejorar la performance aún más.

• La performance obtenida cuando se usa DELETE itab FROM, en vez de f LOOP AT itab WHERE …

DELETE itab. ENDLOOP.mejora con el número de entradas de la tabla interna y el número de líneas a

ser borradas.

WorkAreas vs Field-Symbols

Loop con WorkArea Loop con Field-Symbols

TYPES: BEGIN OF TY_DATA, VALUE TYPE STRING, END OF TY_DATA 

Tabla TAB_INTERNA contiene 500000 entradas DATA: TAB_INTERNA STANDARD TABLE OF TY_DATA DATA: WA_TADA TYPE TY_DATA. 

FIELD-SYMBOLS: <FS_DATA> LIKE LINE OF TAB_INTERNA.

DO 500000 TIMES. APPEND INITIAL LINE TO TAB_INTERNAL ASSIGNIGN <FS_DATA>. <FS_DATA>-VALUE = SY-INDEX ENDDO 

LOOP AT TAB_INTERNA INTO WA_TAB. ENDLOOP.

TYPES: BEGIN OF TY_DATA, VALUE TYPE STRING, END OF TY_DATA 

Tabla TAB_INTERNA contiene 500000 entradas DATA: TAB_INTERNA STANDARD TABLE OF TY_DATA FIELD-SYMBOLS: <FL> LIKE LINE OF TY_DATA. 

FIELD-SYMBOLS: <FS_DATA> LIKE LINE OF TAB_INTERNA.

DO 500000 TIMES. APPEND INITIAL LINE TO TAB_INTERNAL ASSIGNIGN <FS_DATA>. <FS_DATA>-VALUE = SY-INDEX ENDDO 

LOOP AT TAB_INTERNA ASSIGNING <FI>. ENDLOOP.

0,12 microsegundos 0,05 microsegundos

Page 17: Rendimiento en la programación ABAP

• En este ejemplo no se esta haciendo ningún cálculo, modificacion o impresion, que generaria mas

tiempo, solo recorremos los registros, ademas si modificamos algn campo, con el field-symbols,la

modificación es directa pero con la WorkArea habrai que mover los cambios a la tabla interna.

Tipos de datos

Tipos de datos declarados vs. parámetros sin declaración de tipo.

Parámetros sin definición de tipo Parámetros con definición de tipo

PERFORM UP1 USING IX M6-DIMIDM6-ZAEHL M6-ISOCODE M6-ANDECM6-PRIMARY.

FORM UP1 USINGREPEATDIMIDZAEHLISOCODEANDECPRIMARY.

Idéntico código fuente a la izquierda y derecha:

DO REPEAT TIMES.T006-DIMID = DIMID.T006-ZAEHL = ZAEHL.T006-ISOCODE = ISOCODE.T006-ANDEC = ANDEC.T006-PRIMARY = PRIMARY.I1 = REPEAT - SY-INDEX.ENDDO.ENDFORM.

PERFORM UP2 USING IX M6-DIMIDM6-ZAEHL M6-ISOCODE M6-ANDECM6-PRIMARY.

FORM UP2 USINGREPEAT TYPE IDIMID LIKE T006-DIMIDZAEHL LIKE T006-ZAEHLISOCODE LIKE T006-ISOCODEANDEC LIKE T006-ANDECPRIMARY LIKE T006-PRIMARY.

Idéntico código fuente a la izquierda y derecha:

DO REPEAT TIMES.T006-DIMID = DIMID.T006-ZAEHL = ZAEHL.T006-ISOCODE = ISOCODE.T006-ANDEC = ANDEC.T006-PRIMARY = PRIMARY.I1 = REPEAT - SY-INDEX.ENDDO.ENDFORM.

228 microsegundos 161 microsegundos

• Si especifica el tipo de dato a los parámetros en su código fuente, el compilador ABAP/4 puede

optimizar el código completamente. Además el riesgo de usar una secuencia errónea de parámetros en

una instrucción PERFORM es mucho menor.

• Si tiene una extensa cantidad de programas con declaraciones sin tipo, utilice la facilidad provista por

el workbench para realizar una declaración de tipo automática.

Declaración de tipos vs. sin declaración de tipos en Field-symbols

Field-symbols sin tipo Ffield-symbols con declaración de tipo

FIELD-SYMBOLS: <F>.

ASSIGN I1 TO <F>.I2 = <F>.

FIELD-SYMBOLS: <I> type I.

ASSIGN I1 TO <I>.I2 = <I>.

Page 18: Rendimiento en la programación ABAP

I3 = <F>.I4 = <F>.

I3 = <I>.I4 = <I>.

11 microsegundos 7 microsegundos

• Si se especifica el tipo de datos del Field-symbols y de los parámetros en su código fuente, el

compilador ABAP/4 puede optimizar mejor el código.

If vs. Case

If Case

IF C1A = ’A’. WRITE ’1’.ELSEIF C1A = ’B’. WRITE ’2’.ELSEIF C1A = ’C’. WRITE ’3’.ELSEIF C1A = ’D’. WRITE ’4’.ELSEIF C1A = ’E’. WRITE ’5’.ELSEIF C1A = ’F’. WRITE ’6’.ELSEIF C1A = ’G’. WRITE ’7’.ELSEIF C1A = ’H’. WRITE ’8’.ENDIF.

CASE C1A.WHEN ’A’. WRITE ’1’.WHEN ’B’. WRITE ’2’.WHEN ’C’. WRITE ’3’.WHEN ’D’. WRITE ’4’.WHEN ’E’. WRITE ’5’.WHEN ’F’. WRITE ’6’.WHEN ’G’. WRITE ’7’.WHEN ’H’. WRITE ’8’.ENDCASE.

16 microsegundos 7 microsegundos

• La instrucción CASE es clara y un poco más rápida que la construcción IF.

Case vs. Perform I of …

Case Perform I Of …

* (I1 = 5 in this test)CASE I1.WHEN 1. PERFORM PV1.WHEN 2. PERFORM PV2.WHEN 3. PERFORM PV3.WHEN 4. PERFORM PV4.WHEN 5. PERFORM PV5.WHEN 6. PERFORM PV6.WHEN 7. PERFORM PV7.WHEN 8. PERFORM PV8.ENDCASE.

* (I1 = 5 in this test)PERFORM I1 OFPV1PV2PV3PV4PV5PV6PV7PV8.

11 microsegundos 6 microsegundos

• Una forma rápida de llamar a una determinada rutinas usando un índice dado, es usar la instrucción

PERFORM I OF … .

While vs. Do

Do Case

Page 19: Rendimiento en la programación ABAP

I1 = 0.DO.IF C1A NE SPACE. EXIT. ENDIF.ADD 1 TO I1.IF I1 GT 10. C1A = ’X’. ENDIF.ENDDO.

I1 = 0.WHILE C1A = SPACE.ADD 1 TO I1.IF I1 GT 10. C1A = ’X’. ENDIF.ENDWHILE.

8 microsegundos 6 microsegundos

• Si puede use WHILE en vez de una construcción DO+EXIT. WHILE es más fácil para entender y

rápido para ejecutar.

Conversión de Campos

Campos tipos I y P

Tipo P Tipo I

DATA: IP TYPE P.DO 5 TIMES.IP = SY-INDEX * 2.READ TABLE X100 INDEX IP.ENDDO.

DATA: IP TYPE I.DO 5 TIMES.IP = SY-INDEX * 2.READ TABLE X100 INDEX IP.ENDDO.

78 microsegundos 37 microsegundos

• Es mejor usar campos de tipo I para variable que son tipicamente enteras tales como índices.

Constantes tipo F

Literal tipo C Constantes tipo F

DATA:FLOAT TYPE F.

FLOAT = ’3.1415926535897932’.

CONSTANTS:PI TYPE F VALUE ’3.1415926535897932’.

DATA:FLOAT TYPE F.

FLOAT = PI.

22 microsegundo 1 microsegundo

• Usar correctamente las constantes declaradas en vez de literales.

Mezcla de tipos

Varios tipos Unicamente 1 tipo

DATA: F1 TYPE I VALUE 2,F2 TYPE P DECIMALS 2 VALUE ’3.14’,F3 TYPE F.

DATA: F1 TYPE F VALUE 2,F2 TYPE F VALUE ’3.14’,F3 TYPE F.

Page 20: Rendimiento en la programación ABAP

F3 = F1 * F2. F3 = F1 * F2.

46 microsegundos 1 microsegundos

• No mezcle tipos a menos que sea absolutamente necesario.

Literales tipo C y tipo I

Tipo C Tipo I

SY-SUBRC = ’0’.CASE SY-SUBRC.WHEN ’1’.WHEN ’2’.WHEN ’3’.WHEN ’4’.ENDCASE.

SY-SUBRC = ’0’.CASE SY-SUBRC.WHEN ’1’.WHEN ’2’.WHEN ’3’.WHEN ’4’.ENDCASE.

14 microsegundos 6 microsegundos

• Utilice literales numéricos o constantes con un tipo de número en vez de un string de caracteres, si son

tratados como enteros o campos tipo P.

Aritmética

Tipo N Tipo P

DATA:N1(15) TYPE N VALUE ’123456789012345’,N2(15) TYPE N VALUE ’543210987654321’,N3(15) TYPE N.

N3 = N1 + N2.

DATA:P1 TYPE P VALUE ’123456789012345’,P2 TYPE P VALUE ’543210987654321’,P3 TYPE P.

P3 = P1 + P2.

29 microsegundos 8 microsegundos

• Utilice tipos numéricos para operaciones aritméticas.

UTILIZACIÓN DE TABLAS TRANSPARENTES, POOL Y CLUSTERS

Tablas Transparentes y Pool

Cuando seleccione desde una tabla Transparente o Pool, siempre restrinja la sentencia SELECT los

más posible con la opción WHERE. También con campos de datos que pueden no ser parte de la clave.

Esto permite a la Base de Datos evaluar los registros y devolver solamente aquellos que concuerdan

con el criterio de selección.

Tablas transparentes y pool:

Select + Check Select ... Where

Page 21: Rendimiento en la programación ABAP

SELECT * FROM ZZLT2WHERERLDNR = V_LDGRANDRRCTY = ’0’ANDRVERS = ’001’ANDRYEAR = V_YR.CHECK V_CMPNY.CHECK V_ACCT.CHECK V_CNTR.………ENDSELECT.

SELECT * FROM ZZLT2WHERERLDNR = V_LDGRANDRRCTY = ’0’ANDRVERS = ’001’ANDRYEAR = V_YRANDBUKRS = V_CMPNYANDRACCT = V_ACCTANDRCNTR = V_CNTR.…….ENDSELECT

Requiere más memoria y buffer Mas eficientex

Tablas Cluster

Cuando trabaje con tablas cluster hay que hacer exactamente lo contrario del punto anterior. Solo utilice

el comando SELECT, con los campos que son parte de la clave. Si la tabla es una Tabla Cluster se usa

el comando CHECK para eliminar registros después que la selección fue acotada usando la cláusula

WHERE con campos clave.

Las tablas clusters no pueden ser procesadas por la base de datos directamente, las tablas

transparentes si. En la mayoría de los casos forzar a la base de datos a abrir y chequear los campos

(como cuando se usa SELECT y WHERE sobre campos no clave) es menos eficiente que utilizar solo

campos clave en el WHERE y permitir que ABAP verifique los campos no clave después que los datos

son devueltos.

Tablas Cluster:

Para tablas Cluster BSEG con claves MANDT, BUKRS, BELNR, GJAHR, y BUZEI:

Select ... Where Select + Check

SELECT * FROM BSEGWHERE BELNR = BSIK-BELNRANDBUKRS = BSIK-BUKRSANDLIFNR = BSIK-LIFNRANDSHKZG = ’S’ANDKOART = ’K’.……..ENDSELECT.

SELECT * FROM BSEGWHERE BUKRS = BSIK-BUKRSANDREBZG = BSIK-BELNR.CHECK BSIK-LIFNR = BSEG-LIFNR.CHECK BSEG-SHKZG = ’S’.CHECK BSEG-KOART = ’K’.……..ENDSELECT.

Trabajará pero requiere mucha memoria disponible, espacio de Buffer y tiempo de base de datos para desempaquetar y comparar datos. Este trabajo puede ser muy costoso. Puede cargar excesivamente el servidor de base de datos

Trabajará más eficazmente con tablas cluster, especialmente en ambientes de muchos servidores de aplicación.

Atributos de los campos en el WHERE

Page 22: Rendimiento en la programación ABAP

Los campos que se comparan en el WHERE deben tener atributos similares. Si no los tienen el sistema

debe convertirlos cada vez que se realice la comparación. Cuando no se los pueda hacer similares a

travéz de la definición de los campos, se deben mover los datos a campos de trabajo antes de hacer la

comparación.

Por ejemplo :

SELECT * FROM ZZLT2

WHERE RLDNR = LDGR

AND RRCTY = ’0’

AND RVERS = ’001’

AND RYEAR = YEAR.

SELECT * FROM ZZLS2WHERE RLDNR = ZZLT2-RLDNRAND RRCTY = ZZLT2-RRCTYAND BUKRS = ZZLT2-BUKRS.

SELECT * FROM BSEGWHERE BUKRS = ZZLS2-BUKRSAND BELNR = ZZLS2-DOCNRAND GJAHR = ZZLS2-RYEAR

AND BUZEI = ZZLS2-DOCLN.

==> Compara un NUMC 3 con un CHAR 3. Dado que este SELECT se va a ejecutar muchas veces, sería más eficiente mover el campo de datos antes de comenzar el loop del SELECT.

DATA: ZZ_TEMP_DOCLN LIKE BESG-BUZEI.

. . .

SELECT * FROM ZZLT2

WHERE RLDNR = LDGR

AND RRCTY = ’0’

AND RVERS = ’001’

SELECT * FROM ZZLS2WHERE RLDNR = ZZLT2-RLDNRAND RRCTY = ZZLT2-RRCTYAND BUKRS = ZZLT2-BUKRS.

AND RYEAR = YEAR.

MOVE ZZLS2-DOCLN TO ZZ_TEMP_DOCLN.

SELECT * FROM BSEGWHERE BUKRS = ZZLS2-BUKRS

Page 23: Rendimiento en la programación ABAP

AND BELNR = ZZLS2-DOCNRAND GJAHR = ZZLS2-RYEARAND BUZEI = ZZ_TEMP_DOCLN.

Generación de índices secundarios

• Toda tabla SAP tiene un índice primario, que consiste de los campos claves que el usuario definió en

el proceso de creación de la tabla. El índice puede no ser utilizado si no se tienen todas las claves en la

cáausula WHERE del SELECT o si la cláusula WHERE no es correctamente especificada. En este caso

el administrador de la base de lee toda la tabla.

• El diccionario de datos de SAP soporta un máximo de 16 índices por cada tabla.

• Los índices deberían, generalmente, tener menos de cinco campos.

• Los campos más selectivos de la tabla deberían estar primeros en el índice (por ejemplo el campo

MANDT en casi todas las tablas).

• En general si una condición incluye el operador OR, el optimizador detiene su procesamiento ( e

invoca una búsqueda completa de la tabla ) tan pronto como es encontrado el primer OR. La posible

excepción es un OR que proponga una separada y única condición para la evaluación.

Por Ejemplo :

La tabla ZTABLE se define con el siguiente índice.

Nombre del campoFIELDC CHARFIELDF CHAR

SELECT * FROM ZTABLE WHEREFIELDC = ’ABC’ AND( FIELDF = ’12’ OR FIELDF = ’13’)

SELECT * FROM ZTABLE WHERE( FIELDC = ’ABC’ AND FIELDF = ’12’ ) OR( FIELDC = ’ABC’ AND FIELDF = ’13’)

No será utilizado el índice secundario El índice será utilizado como se esperaba

• Las cláusulas IN frecuentemente se interpretan igual que las OR y pueden llevar al mismo problema

del punto anterior.

• La creación de índices adicionales bajará la performance en las funciones de inserción de registros en

la tabla. En general esto tiene un impacto alto si existen muchos índices sobre la misma tabla.

• Un campo de un índice es válido solo si todos los campos que lo preceden son utilizados en el

WHERE del SELECT.

Por Ejemplo :

Page 24: Rendimiento en la programación ABAP

La tabla ZTABLE se define con el siguiente índice.

Nombre del campo Tipo LongitudFIELDA CHAR 3FIELDB CHAR 3FIELDC CHAR 2

SELECT * FROM ZTABLEWHERE FIELDA = ’ABC’AND FIELDB = ’XYZ’AND FIELDD = ’DEFG’.

SELECT * FROM ZTABLEWHERE FIELDA = ’ABC’AND FIELDB = ’XYZ’AND FIELDC = ’12’.

No será utilizado el índice secundario El índice será utilizado como se esperaba

Enlaces

ABAP Fine Tuning http://www.sap-img.com/abap/abap-fine-tuning.htm

Use of FOR ALL

ENTRIES http://www.thespot4sap.com/articles/SAPABAPPerformanceTuning_ForAllEntries.asp

WorkAreas vs Field-Symbols http://atejada.blogspot.com/2008/01/workarea-vs-field-symbols.html

Categoría: 

Manuales