MUNDOSAP

MUNDOSAP (foro/index.php)
-   Programación ABAP IV (foro/forumdisplay.php?f=4)
-   -   mejora rendimiento (foro/showthread.php?t=39828)

budista1 09/11/10 13:24:01

mejora rendimiento
 
¿Cómo mejoro rendimiento a estos 2 selects? (alternativas)

SELECT * INTO TABLE it_ass_tipus
FROM zef_ass_tipus
WHERE retencio_irpf = 'X' AND
tipus_ajust <> '/'.

* Obtenim les dades de la sac
SELECT * INTO TABLE it_sac
FROM zef_sac FOR ALL ENTRIES IN it_ass_tipus
WHERE bukrs = p_bukrs AND
gjahr = p_gjahr AND
id_tipus_ass = it_ass_tipus-tipus_complert AND
belnr IN s_belnr AND
tercer IN s_tercer AND
estat IN s_estat AND
estat <> '99' AND
hkont IN s_hkont AND
tercer IN r_terc.

GRACIAS Y SALUDOS ABAPEROS

jtristan 09/11/10 14:06:37

Desconociendo el tamaño de las tablas así como los índices que estén creados podrías hacer un JOIN en vez de un FOR ALL ENTRIES. El for all entries sino recuerdo mal no deja de ser un UNION por cada registro de la tabla temporal.

Sería algo así:
SELECT * INTO TABLE table
FROM zef_ass_tipus
LEFT JOIN
zef_sac
ON
zef_ass_tipus~tipus_complert = zef_sac~id_tipus_ass
WHERE retencio_irpf = 'X' AND
tipus_ajust <> '/' AND
bukrs = p_bukrs AND
gjahr = p_gjahr AND
belnr IN s_belnr AND
tercer IN s_tercer AND
estat IN s_estat AND
estat <> '99' AND
hkont IN s_hkont AND
tercer IN r_terc.


Un saludo.

budista1 09/11/10 15:55:29

Muchas Gracias
 
Gracias compañero!!

voy a probarlo.

La tabla ZEF_SAC tiene unos 300 mil registros, los campos clave son

MANDT
BUKRS
GJAHR
NUM_SAC

La tabla ZEF_ASS_TIPUS solo unos 500 registros

campos clave :
MANDT
TIPUS
ESTAT


Por qué transacción puedo evaluar el rendimiento?
(a parte de la se30)

Saludos!

Mari.Sole 09/11/10 23:06:58

Hola,
Una simple acotación. Podrías probar de eliminar del SELECT la clausula <> eso hace que se pierda mucha performance en el acceso a la BD.
Si eliminas esa cluasula luego de la selección de datos deberías agregar una rutina que al resultado obtenido de esa selección (almacenado en tabla interna) deberías recorrerla y eliminar los registros cuya condicion quitaste del SELECT.

Saludos!

VLozano 10/11/10 07:03:59

Antes que nada:
1. FOR ALL ENTRIES:
si vas a usar la cláusula FOR ALL ENTRIES IN, asegúrate primero de que la tabla interna sobre la que se va a filtrar tiene datos. En tu caso, si la primera SELECT no retorna datos, la segunda lee TODOS LOS REGISTROS DE LA TABLA. Y eso duele.

2. SELECT *
No es conveniente utilizar esta sentencia. Es mucho más rápido de escribir, pero a no ser que realmente necesites todos los datos de la tabla, estás metiéndole presión al servidor de datos (y al de aplicaciones).
------------------------------------------------------------------
Y ahora una respuesta (que quizá no te guste)

Alternativas al FOR ALL ENTRIES:
- INNER JOIN
- SELECT SINGLE en un LOOP

La mayoría de desarrolladores "a la antigua" (entre los que me podrías incluir) te dirían que la última es un suicidio. No es cierto. La elección entre las tres posibilidades depende de la cantidad (y reparto entre tablas) de datos a leer, de si se utilizan los índices en las condiciones de selección, y de la carga de memoria que pueda tolerar tu servidor.

Viendo las condiciones de la segunda SELECT, podríamos deducir que el campo que usas para filtrar en el FOR ALL ENTRIES no forma parte de la clave ni empieza un índice. Si es el caso, el INNER JOIN podría llegar a ser contraproducente.

Si las cláusulas WHERE que has dado usan índices, y el rendimiento sigue siendo malo (¿seguro que el cuello de botella está ahí?), quizá deberías usar otra aproximación al problema. Por ejemplo, si realizas un tratamiento masivo en un LOOP posterior sobre la primera tabla, en el que realizas un READ TABLE para coger los datos de la segunda, quizá te interesaría intentar un SELECT-LOOP-SELECT. Mucha gente se llevaría ahora las manos a la cabeza, pero con los nuevos motores de BBDD y el rendimiento del que son capaces los servidores hoy en día, ese gesto está desfasado. Te lo dice un abuelete.

budista1 10/11/10 10:36:43

gracias pero..
 
Antes de nada, muy agradecido por vuestra ayuda.

Hice una 1a prueba cambiando unas selects por el join que me dijo un compañero de mundosap. De momento el rendimiento no ha mejorado :-(

SELECT * INTO CORRESPONDING FIELDS OF TABLE it_sac
FROM zef_sac
LEFT JOIN
zef_ass_tipus
ON
zef_sac~id_tipus_ass = zef_ass_tipus~tipus_complert
WHERE
* retencio_irpf = 'X'
*AND
*tipus_ajust <> '/' AND
bukrs = p_bukrs AND
gjahr = p_gjahr AND
belnr IN s_belnr AND
tercer IN s_tercer AND
*estat IN s_estat AND
*estat <> '99' AND
hkont IN s_hkont AND
tercer IN r_terc.

robert_milan 10/11/10 10:41:51

Yo lo que haria
 
¿Cómo mejoro rendimiento a estos 2 selects? (alternativas)
* it_ass_tipus definela con campos que necesites *
* it_sac definela con campos que necesites *
SELECT [Pon los campos que necesites] INTO TABLE it_ass_tipus
FROM zef_ass_tipus
WHERE retencio_irpf = 'X' AND
tipus_ajust <> '/'.
If sy-subrc = 0.
* Obtenim les dades de la sac
SELECT [Pon los campos que necesites] INTO TABLE it_sac
FROM zef_sac FOR ALL ENTRIES IN it_ass_tipus
WHERE bukrs = p_bukrs AND
gjahr = p_gjahr AND
id_tipus_ass = it_ass_tipus-tipus_complert AND
belnr IN s_belnr AND
tercer IN s_tercer AND
estat IN s_estat AND
estat <> '99' AND
hkont IN s_hkont AND
tercer IN r_terc.

A la tabla ZEF_SAC creale un indice con los campos que usas aqui.
endif.

Saludos

budista1 10/11/10 16:15:01

nueva idea
 
Y si hago 2 selects normales, lo meto en 2 tablas internas y luego hago

un loop de una tabla
y read table binary search con la otra?

Podría mejorar la cosa:p

VLozano 11/11/10 06:33:47

Eso dependerá de algunos factores, como el número de registros de cada tabla (sobretodo de la segunda), la memoria del servidor, su configuración...

Yo antes que intentar eso haría pruebas de rendimiento con un SELECT-LOOP-SELECT, como te he comentado antes. Siempre estás a tiempo de echarte atrás, pero probablemente te sorprendas.


Husos Horarios son GMT. La hora en este momento es 20:57:47.

www.mundosap.com 2006 - Spain
software crm, crm on demand, software call center, crm act, crm solutions, crm gratis, crm web