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 deter minada ya que fueron medidos en una server específico, con una carga de trabajo despreciable. Además de las consideraciones sobre sobre sentencias y proc edimientos 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_CLNT CHECK: VERI_CLNT-ARG1 = ¶7¶. ENDSELECT.
SELECT * FROM VERI_CLNT WHERE ARG1 = ¶7¶. ENDSELECT.
88,234 microsegundos microse gundos
4,907 microsegundos microsegu ndos
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 considerablemente mejor.
Select single vs. Select-Endselect Select ... Endselect
Select single * ...
SELECT * FROM VERI_CLNT WHERE ARG1 = ¶7¶ AND ARG2 = ¶ ¶. ENDSELECT.
SELECT SINGLE * FROM VERI_CLNT WHERE ARG1 = ¶7¶ AND ARG2 = ¶ ¶.
4,549 microsegundos microse gundos
4,160 microsegundos microse gundos
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 T100 WHERE SPRSL = ¶000¶. CHECK: T100-MSGNR > C4A. C4A = T100-MSGNR. ENDSELECT.
SELECT MAX(MSGNR) FROM T100 INTO C4A WHERE SPRSL = ¶D¶ AND ARBGB = ¶00¶.
221,213 microsegundos microsegu ndos
24,470 microsegundos microse gundos
Si requiere encontrar el valor máximo, mínimo, sumatoria y promedio o la cantida d de una columna de la base de datos; use las funciones agregadas en vez de agregar instrucciones instrucciones para realizar r ealizar el cálculo.
Select con Vistas Instrucciones Instrucciones Select anidadas
Select con vistas
SELECT * FROM DD01L WHERE DOMNAME LIKE ¶CHAR%¶ AND AS4LOCAL = ¶A¶. SELECT SINGLE * FROM DD01T WHERE DOMNAME = DD01L-DOMNAME AND AS4LOCAL = ¶A¶ AND AS4SERVERS = DD01L-AS4VERS AND DDLANGUAJE = SY-LANGU. ENDSELECT.
SELECT * FROM DD01V WHERE DOMNAME LIKE ¶CHAR%¶ AND DDLANGUAJE = SY-LANGU. ENDSELECT.
1,472,996 microsegundos micros egundos
308,670 microsegundos microsegu ndos
Para procesar un join, use una vista en vez de instrucciones instrucciones Select anidadas. a nidadas.
Select con soporte de buffer Select sin soporte soport e de buffer
Select con soporte de buffer
SELECT SINGLE * FROM T100 BYPASSING BUFFER WHERE SPRSL = ¶D¶ AND ARBGB = ¶00¶ AND MSGNR = ¶999¶.
SELECT SINGLE * FROM T100 WHERE SPRSL = ¶D¶ AND ARBGB = ¶00¶ AND MSGNR = ¶999¶.
4,395 microsegundos microse gundos
242 microsegundos micros egundos
Para tablas de solo lectura y uso fr ecuente, 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_CLNT SET 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
SELECT * FROM T100 WHERE ARBGB = ¶00¶ AND MSGNR = ¶999¶. ENDSELECT.
SELECT * FROM T002. SELECT * FROM T100 WHERE SPRSL = T002-SPRAS AND ARBGB = ¶00¶ AND MSGNR = ¶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 ta ble 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 WHERE DOMNAME LIKE ¶CHAR%¶ AND AS4LOCAL = ¶A¶. ENDSELECT.
SELECT DOMNAME FROM DD01L INTO DD01L-DOMNAME WHERE DOMNAME LIKE ¶CHAR%¶ AND AS4LOCAL = ¶A¶. ENDSELECT.
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 entradas LOOP AT TAB. INSERT INTO VERI_CLNT VALUES TAB. ENDLOOP.
* Tabla TAB con 100 entradas INSERT 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 . DO 200 TIMES. IF = ¶(¶ OR = ¶)¶. " Alguna operación. EXIT. ENDIF. ASSIGN +1 TO . ENDDO.
IF CHA(200) CA ¶()¶. " Alguna operación. ENDIF.
1,123 microsegundos
443 microsegundos
Utilice los operadores especiales C O, 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 MOVE ¶Jane¶ TO CMA. MOVE ¶Miller¶ TO CMB. MOVE ¶New York City¶ TO CMC. I1 = STRLEN(CMA). I2 = STRLEN(CMB). 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 valor final de CHA. 93 microsegundos
Usando la instrucción CONCATENATE
MOVE ¶Jane¶ TO CMA. MOVE ¶Miller¶ TO CMB. MOVE ¶New York City¶ TO CMC. CONCATENATE ¶Mrs.¶ CMA CMB ¶from¶ CMC INTO CHA SEPARATE BY SPACE.
"Mrs. Jane Miller from New York City" es el valor final de CHA. 28 microsegundos
Utilice la instrucción CONCATENATE en vez de adicionar instrucciones de programación.
Borrando espacios en blanco Corriendo SY-FDPOS lugares
" CLA contiene el string " ¶ " Editor line n".
Usando SHIFT ... LEFT DELETING LEADING
" CLA contiene el string " ¶ " Editor line n".
IF CLA CN SPACE. ENDIF. SHIFT CLA BY SY-FDPOS PLACES LEFT
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¶ EXPORTING STRING1 = T100-ARBGB STRING2 = T100-MSGNR STRING3 = T100-TEXT IMPORTING STRING = CLA EXCEPTIONS TOO_SMALL = 01.
CONCATENATE T100-ARBGB T100-MSGNR T100-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. STRING_CONCATENATE STRING_SPLIT
p
STRING_LENGTH
p
CONCATENATE
SPLIT p
STRING_CENTERED
STRLEN() p
STRING_MOVE_RIGHT
WRITE ... TO ... CENTERED p
WRITE ... TO ... RIGHT-JUSTIFIED
articiones de strings
P
Uso de SEARCH y MOVE con offset
Uso de la instrucción SPLIT
CMA contiene ¶(410)-45174-6654312¶ y será dividido en 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. 66 microsegundos
CMA contiene ¶(410)-45174-6654312¶ y será dividido en Código de Area, Teléfono1 y Teléfono2 SPLIT CMA AT ¶-¶ INTO AREA_CODE TEL_NO1 TEL_NO2.
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
DATA: BEGIN OF STR,LINE TYPE X, END OF STR,CHECK_SUM TYPE I. MOVE ¶KALEBVPQDSCFG¶ TO CLA.
Obtener el CHECK_SUM con strlen()
DATA: BEGIN OF STR,LINE TYPE X, END OF STR,CHECK_SUM TYPE I. MOVE ¶KALEBVPQDSCFG¶ TO CLA.
I1 = STRLEN(CLA). DO 64 TIMES VAYING STR FROM CLA DO I1 TIME VARYING STR FROM NEXT CLA+1. CLA NEXT CHECK STR NE SPACE. CLA+1. ADD STR-LINE TO CHECK_SUM. CHECK STR NE SPACE. ADD STR-LINE TO CHECK_SUM ENDDO. ENDDO. 597 microsegundos
171 microsegundos
Utilice la función STRLEN() para r estringir la cantidad de ciclos que debe efectuar la instrucción DO, cuando determina un CHECK_SUM.
Tablas internas 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 TAB_DES contiene 1000 entradas REFRESH TAB_DEST. LOOP AT TAB_SRC. READ TABLE TAB_DEST WITH KEY K = TAB_SRC-K BINARY SEARCH. INSERT TAB_SRC INTO T AB_DEST INDEX SY-TABIX. ENDLOOP. 98,545 microsegundos
REFRESH TAB_DEST. LOOP AT TAB_SRC. APPEND TAB_SRC TO TAB_DEST. ENDLOOP. SORT TAB_DEST BY K. 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 TAB_DES contiene 1000 entradas de las cuales 500 son diferentes REFRESH TAB_DEST. LOOP AT TAB_SRC. READ TABLE TAB_DEST WITH KEY K = TAB_SRC-K BINARY SEARCH. IF SY-SUBRC <> 0. INSERT TAB_SRC INTO T AB_DEST INDEX SY-TABIX. ENDIF. ENDLOOP. 43,469 microsegundos
Generación en tres pasos
TAB_DES contiene 1000 entradas de las cuales 500 son diferentes REFRESH TAB_DEST. LOOP AT TAB_SRC. APPEND TAB_SRC TO TAB_DEST. ENDLOOP. SORT TAB_DEST BY K. DELETE ADJACENT DUPLICATES FROM TAB_DEST COMPARING K. 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.
iferentes formas de acceso con clave
D
Acceso vía una clave default implícita
Acceso vía una clave explícitamente asignada
Tabla TAB contiene 30 entradas de 500 bytes cada. La instrucción READ finaliza con SYSUBRC=4
Tabla TAB contiene 30 entradas de 500 bytes cada. La instrucción READ finaliza con SYSUBRC=4
MOVE SPACE TO TAB. TAB-K = ¶X¶. READ TABLE TAB BINARY SEARCH.
READ TABLE TAB WITH KEY K = ¶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 Tabla TAB contiene 100 entradas de 500 bytes cada una, solo 5 coinciden con la clave de búsqueda.
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.
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 interna mente. 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 100 Tabla TAB_SRC contiene 100 entradas de 100 Bytes cada. Bytes cada. REFRESH TAB_DEST. LOOP AT TAB_SRC INTO TAB_DEST. APPEND TAB_DEST. ENDLOOP.
949 microsegundos
TAB_DEST[] = TAB_SRC[].
314 microsegundos
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 ta bla puede accederse por itab[ ]
Ordenando tablas internas SORT itab con una clave de ordenamiento por default Tabla TAB contiene 100 entradas de 500 bytes cada una
SORT TAB. 2,026 microsegundos
SORT itab con una clave específica
Tabla TAB contiene 100 entradas de 500 bytes cada una SORT TAB BY K. 821 microsegundos
La ejecución sera más rápida si se especifica la mayor cantida d posible de claves de ordenamiento.
Loops Anidados Loops anidados
Loop de cursor paralelo
Tabla TAB1 contiene 100 entradas de 100 bytes cada una Tabla TAB2 contiene 10 * 100 = 1000 Tabla TAB1 contiene 100 entradas de 100 entradas de 100 bytes cada una bytes cada una Tabla TAB2 contiene 10 * 100 = 1000 I2 = 1. entradas de 100 bytes cada una LOOP AT TAB1. LOOP AT TAB2 FROM I2. LOOP AT TAB1. IF TAB2-K <> TAB1-K. LOOP AT TAB2 WHERE K = TAB1-K. I2 = SY-TABIX. " ... EXIT. ENDLOOP. ENDIF. ENDLOOP. " ... 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 paral elo 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 ligera mente 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 líneas Tabla TAB_DEST contiene 1000 entradas 500 bytes cada una, las líneas 450 a 550 serán borradas.
Ordenando al kernel a realizar el trabajo
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.
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,000 de las cuales tiene diferente claves LOOP AT TAB_SRC. READ TABLE TAB_DEST WITH KEY K = TAB_SRC-K BINARY SEARCH. IF SY-SUBRC = 0. ADD: TAB_SRC-VAL1 TO TAB_DEST-VAL1, TAB_SRC-VAL2 TO TAB_DEST-VAL2 MODIFY TAB_DEST INDEX SYTABIX. ELSE. INSERT TAB_SRC INTO T AB_DEST INDEX SY-TABIX. ENDIF. ENDLOOP. 1,580,904 microsegundos
Tabla TAB_SRC contiene 10,000 entradas, 5,000 de las cuales tiene diferente claves LOOP AT TAB_SRC. COLLECT TAB_SRC INTO TAB_DEST. ENDLOOP. SORT TAB_DEST BY K.
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 acer camiento READ/INSERT no es malo, pero para cantidades mayores de datos (>1000), COLLECT es mucho más rápido. 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 Tabla TAB contiene 1000 entradas de 100 bytes bytes cada. El READ finaliza con SY-SUBRC=4 cada. El READ finaliza con SY-SUBRC=4 READ TABLE TAB WITH KEY K = ¶X¶. READ TABLE TAB WITH KEY K = ¶X¶ BINARY SEARCH. 1,452 microsegundos
29 microsegundos
Si la tabla interna ti ene 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 búsqueda lineal ¢Sin índice secundario Tabla TAB contiene 1000 entradas. El READ usa las 500 primeras entradas. READ TABLE TAB WITH KEY DATE = SY-DATUM. IF SY-SUBRC = 0. ... ENDIF.
798 microsegundos
Búsqueda binaria usando índice secundario Tabla TAB contiene 1000 entradas. El READ usa las 500 primeras entradas. READ TABLE TAB_INDEX WITH KEY DATE = SY-DATUM BINARY SEARCH. IF SY-SUBRC = 0. READ TABLE TAB INDEX TAB_INDEX-INDX. ... ENDIF. 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 .
U
sando 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
El ancho de la línea de la tabla TAB es 500 bytes
El ancho de la línea de la tabla TAB es 500 bytes
TAB = TAB_WA. APPEND TAB.
APPEND TAB_WA TO TAB.
17 microsegundos
9 microsegundos
Evite los MOVEs innecesarios, usando las operaciones explícitas de áreas de tra bajo. 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 = SPACE LOOP AT TAB1. READ TABLE TAB2 INDEX SY-TABIX. IF TAB1 <> TAB2. TAB_DIFFERENT = ¶X¶. EXIT. ENDIF. ENDLOOP. ENDIF. IF TAB_DIFFERENT = SPACE. " ... ENDIF. 1,774 microsegundos
Tablas TAB1 y TAB2 tienen cada 100 entradas de 100 Bytes cada IF TAB1[] = TAB2[]. " ... ENDIF.
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[].
niendo tablas internas
U
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
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 KEY K = TAB1-K BINARY SEARCH. IF SY-SUBRC = 0. ... ENDIF. ENDLOOP.
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 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. 26,826 microsegundos
Ordenado al kernel a realizar el trabajo
Tabla TAB_DEST contiene 1000 entradas de 100 bytes cada y contiene 500 pares de duplicados DELETE ADJACENT DUPLICATES FROM TAB_DEST COMPARING K.
4,159 microsegundos
Con la nueva variante del DELETE , DELETE ADJACENT DUPLICATES, la tarea del borrado es transferida al kernel.
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 500 bytes cada, estas coinciden el WHERE condition
Tabla TAB_DEST contiene 1000 entradas de 500 bytes cada, estas coinciden el WHERE condition
LOOP AT TAB_DEST WHERE K = KVAL. DELETE TAB_DEST. ENDLOOP.
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.
Work Areas vs Field-Symbols Loop con WorkArea
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: LIKE LINE OF TAB_INTERNA. DO 500000 TIMES. APPEND INITIAL LINE TO TAB_INTERNAL ASSIGNIGN . -VALUE = SY-INDEX ENDDO LOOP AT TAB_INTERNA INTO WA_TAB. ENDLOOP. 0,12 microsegundos
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 FIELD-SYMBOLS: LIKE LINE OF TY_DATA. FIELD-SYMBOLS: LIKE LINE OF TAB_INTERNA. DO 500000 TIMES. APPEND INITIAL LINE TO TAB_INTERNAL ASSIGNIGN . -VALUE = SY-INDEX ENDDO LOOP AT TAB_INTERNA ASSIGNING . ENDLOOP. 0,05 microsegundos
En este ejemplo no se esta haciendo ningún cálculo, modificacion o impresion, que generaria mas tiempo, solo recorremos los r egistros, 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-DIMID M6-ZAEHL M6-ISOCODE M6-ANDEC M6-PRIMARY.
PERFORM UP2 USING IX M6-DIMID M6-ZAEHL M6-ISOCODE M6-ANDEC M6-PRIMARY.
FORM UP1 USING REPEAT DIMID ZAEHL ISOCODE ANDEC PRIMARY.
FORM UP2 USING REPEAT TYPE I DIMID LIKE T006-DIMID ZAEHL LIKE T006-ZAEHL ISOCODE LIKE T006-ISOCODE ANDEC LIKE T006-ANDEC PRIMARY LIKE T006-PRIMARY.
Idéntico código fuente a la izquierda y derecha:
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 - S Y-INDEX. ENDDO. ENDFORM.
DO REPEAT TIMES. T006-DIMID = DIMID. T006-ZAEHL = ZAEHL. T006-ISOCODE = ISOCODE. T006-ANDEC = ANDEC. T006-PRIMARY = PRIMARY. I1 = REPEAT - S Y-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.
D
eclaració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: .
FIELD-SYMBOLS: type I.
ASSIGN I1 TO . I2 = . I3 = . I4 = .
ASSIGN I1 TO . I2 = . I3 = . I4 = .
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 OF PV1 PV2 PV3 PV4 PV5 PV6 PV7 PV8.
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
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.
CONSTANTS: PI TYPE F VALUE ¶3.1415926535897932¶.
FLOAT = ¶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.
F3 = F1 * F2.
F3 = F1 * F2.
46 microsegundos
1 microsegundos
No mezcle tipos a menos que sea absoluta mente 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.
DATA: P1 TYPE P VALUE ¶123456789012345¶, P2 TYPE P VALUE ¶543210987654321¶, P3 TYPE P.
N3 = N1 + N2.
P3 = P1 + P2.
29 microsegundos
8 microsegundos
Utilice tipos numéricos para operaciones aritméticas.
TILIZACIÓN DE TABLAS TR ANSPARENTES, POOL Y CLU STERS U
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
SELECT * FROM ZZLT2 WHERERLDNR = V_LDGR ANDRRCTY = ¶0¶ ANDRVERS = ¶001¶ ANDRYEAR = V_YR. CHECK V_CMPNY. CHECK V_ ACCT. CHECK V_CNTR. «««
SELECT * FROM ZZLT2 WHERERLDNR = V_LDGR ANDRRCTY = ¶0¶ ANDRVERS = ¶001¶ ANDRYEAR = V_YR ANDBUKRS = V_CMPNY ANDR ACCT = V_ ACCT ANDRCNTR = V_CNTR. ««.
ENDSELECT.
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 a brir 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 BSEG WHERE BELNR = BSIK-BELNR ANDBUKRS = BSIK-B UKRS ANDLIFNR = BSIK-LI FNR ANDSHKZG = ¶S¶ ANDKOART = ¶K¶. ««.. ENDSELECT.
SELECT * FROM BSEG WHERE BUKRS = BSIK-BUKRS ANDREBZG = BSIK-BELNR. CHECK BSIK-LI FNR = BSEG-LI FNR. 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 Trabajará más eficazmente con tablas cluster, comparar datos. Este trabajo puede ser especialmente en ambientes de muchos muy costoso. Puede cargar servidores de aplicación. excesivamente el servidor de base de datos
Atributos
de los campos en el WHERE
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 ZZLS2 WHERE RLDNR = ZZLT2-RLDNR AND RRCTY = ZZLT2-RRCTY AND BUKRS = ZZLT2-BUKRS.
SELECT * FROM BSEG WHERE BUKRS = ZZLS2-BUKRS AND BELNR = ZZLS2-DOCNR AND GJAHR = ZZLS2-RYEAR AND BUZEI = ==> Compara un NUMC 3 con un CHAR 3. Dado que este ZZLS2SELECT se va a ejecutar muchas veces, sería más eficiente mover DOCLN. 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¶ AND RYEAR = YEAR. SELECT * FROM ZZLS2 WHERE RLDNR = ZZLT2-RLDNR AND RRCTY = ZZLT2-RRCTY AND BUKRS = ZZLT2-BUKRS.
MOVE ZZLS2-DOCLN TO ZZ_TEMP_DOCLN.
SELECT * FROM BSEG WHERE BUKRS = ZZLS2-BUKRS AND BELNR = ZZLS2-DOCNR AND GJAHR = ZZLS2-RYEAR AND 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 campo
Tipo
FIELDC
CHAR
3
FIELDF
CHAR
3
Longitud
SELECT * FROM ZTABLE WHERE FIELDC = ¶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 : La tabla ZTABLE se define con el siguiente índice. Nombre del campo
Tipo
FIELDA
CHAR
3
FIELDB
CHAR
3
FIELDC
CHAR
2
Longitud
SELECT * FROM ZTABLE WHERE FIELDA = ¶ABC¶ AND FIELDB = ¶XYZ¶ AND FIELDD = ¶DEFG¶.
SELECT * FROM ZTABLE WHERE FIELDA = ¶ABC¶ AND FIELDB = ¶XYZ¶ AND FIELDC = ¶12¶.
No será utilizado el índice secundario
El índice será utilizado como se esperaba
Enlaces y y
y
ABAP Fine Tuning http://www.sap-img.com/abap/abap-fine-tuning.htm Use of FOR ALL ENTRIES http://www.thespot4sap.com/articles/SAPABAPPerformanceTuning_ForAllEntr ies.asp WorkAreas vs Field-Symbols http://atejada.blogspot.com/2008/01/workarea-vsfield-symbols.html