MUNDOSAP

Regresar   MUNDOSAP > DESARROLLO > Programación ABAP IV
Nombre de Usuario
Contraseña
Home Descargas Registrar FAQ Miembros Calendario Buscar Temas de Hoy Marcar Foros Como Leídos




 
Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Viejo 14/12/10, 10:53:39
MarianitoSAPO MarianitoSAPO is offline
Junior Member
 
Fecha de Ingreso: oct 2010
Mensajes: 7
Necesito hacer un INNER JOIN de 3 tablas eficiente

Tengo 3 tablas:

LFA1:
- lifnr (Clave)
- land1
- ...

LFB1:
- lifnr (Clave)
- bukrs (Clave)
- pernr
- ...

LFBK:
- lifnr (Clave)
- banks (Clave)
- bankl (Clave)
- bankn (Clave)
- bkont
- ...

lo que necesito es un
INNER JOIN entre LFA1 y LFB1 en lifnr
y ésta un LEFT OUTER JOIN con la LFBK en lifnr


Mi primera solución fue:
select lifnr land1 ....
from LFA1 as a INNER JOIN LFB1 as b on ....
OUTER JOIN ....
pero me dijeron que era ineficiente, que usara FOR ALL ENTRIES


entonces implementé lo siguiente:


El gran problema es que el campo lifnr
NO es clave de la tabla LFB1 por lo tanto debo
anidar un loop, y además para la condición
LEFT OUTER JOIN debo anidar otro loop
ya que lifnr tampoco es clave de LFBK.

Como imaginarán, esto tarda un poco mas que una
eternidad.

Existe una solución mas eficiente???, cuando usamos
FOR ALL ENTRIES y los campos que accedemos
no son claves (No podemos usar READ TABLE) y
por lo tanto debemos anidar loops.

Además de la ineficiencia, con la condición
LEFT OUTER JOIN se me plantéo que el APPEND
del loop mas interno debería hacer dentro
del loop si consiguió algún registro,
SINO fuera (con las campos NULL) si no consiguio
ningún registro.
Estaría bien, eso?

Saludos,
Gracias
Responder Con Cita
  #2  
Viejo 14/12/10, 12:42:27
Avatar de ppchico
ppchico ppchico is offline
Senior Member
 
Fecha de Ingreso: oct 2006
Localización: Málaga
Mensajes: 144
Lo mejor que puedes hacer, es chequear la eficiencia en SE30. Accede a esa transacción y pulsa en TIPS & TRICKS. Una vez dentro, declara las variables etc. y pon los códigos con los INNER y con el código LOOP y lo comparas... no olvides ejecutarlo varias veces, puesto que cambia en ocasiones dependiendo de la conexión a la BBDD los índices etc..

A ver si te vale eso!
Suerte.
Javier.
Responder Con Cita
  #3  
Viejo 14/12/10, 13:28:00
MarianitoSAPO MarianitoSAPO is offline
Junior Member
 
Fecha de Ingreso: oct 2010
Mensajes: 7
Gracias por tu ayuda,
calcule el performance, y el resultado fue:
Usando Select .... INNER JOIN .... LEFT JOIN ....:
33 seg, 95%bd resto Abap y sistema

Usando For All Entries:
797 seg(24 veces mas lento)
y aproxmadamente 98% Abap y resto sistema y BD.

Es increible la diferencia,
mi duda es
cuando es mas performante un INNER JOIN que un FOR ALL ENTRIES?

Mi hipotesis:
Calculo que es mejor un FOR ALL ENTRIES cuando accedemos
por claves a las tablas (Y podemos usar READ TABLE),
el cuál no es mi caso, y por lo tanto debo anidar 3 loops.
Responder Con Cita
  #4  
Viejo 14/12/10, 13:33:57
Avatar de ppchico
ppchico ppchico is offline
Senior Member
 
Fecha de Ingreso: oct 2006
Localización: Málaga
Mensajes: 144
Esto depende mucho también de las tablas etc. Por ejemplo, las tablas de documentos de material son tablas muy pesadas, y la selección aun accediendo por clave, si la tabla que usas para el FOR ALL ENTRIES es muy pesada, va a dar también un tiempo de respuesta demasiado alto... Lo mejor para optimizarlo es en primer lugar, traer solo los datos que necesitas... el SELECT * en tablas con bastantes datos puede hacer lento el acceso a BBDD, mientras que igual solo necesitas 20 o 30 campos de esa tabla... por otro lado, a mi personalmente me gusta hacer el acceso a base de datos de una vez, y luego tratar los datos recuperados. En tu caso, yo creo que podría ser factible una mezcla de ambas cosas... hacer el LEFT OUTER JOIN por un lado (Para evitar anidad dos bucles) y recuperar el resto de la información por otro lado... y una vez que lo tengas en ambas tablas, montar la tabla final... pero esto es cuestión también de probarlo!!

Suerte pues!! Y ojalá encuentres la solución más optima!

Un Saludo,
Javier.
Responder Con Cita
  #5  
Viejo 15/12/10, 10:39:57
VLozano VLozano is offline
Senior Member
 
Fecha de Ingreso: nov 2009
Mensajes: 124
¿Compruebas que el primer SELECT devuelva datos antes de ejecutar el FOR ALL ENTRIES? En caso de no hacerlo, si no hay datos el programa baja TODA LA TABLA, ignorando totalmente el WHERE... a partir de ahí, todo se va al carajo.

La elección entre JOIN, FOR ALL ENTRIES y subqueries (LOOP-SELECT) debe hacerse con cuidado, y teniendo en cuenta muchos factores, como el tamaño de las tablas, los índices utilizables, la velocidad y la carga del servidor de datos...

En tu caso yo haría una tercera prueba: INNER JOIN + FOR ALL ENTRIES.
__________________
"Porque algunos sabemos que somos parte del problema"
Responder Con Cita
  #6  
Viejo 15/12/10, 17:16:18
cubanito cubanito is offline
Junior Member
 
Fecha de Ingreso: nov 2006
Mensajes: 13
Post

Hola MarianitoSAPO...
LIFNR si es llave en las tres tablas... y a menos que tengan activos índices diferentes, si puedes usar ese campo como llave y hasta me atrevería a decirte que sería mucho mas rápido un INNER JOIN.
Por otro lado, es REGLA INVIOLABLE asegurarse SIEMPRE antes de hacer un FOR ALL ENTRIES que la tabla usada para ello no venga VACÍA!!!

Y por último, el código está muy mal hecho!!! No hay ninguna necesidad de usar esos LOOPS anidados!!! No necesitas usar ese AUX2 para hacerle ese LOOP a AUX3 ya que el LIFNR es el mismo en todas desde AUX1.
por lo tanto podrías dejarlo así:
LOOP AUX1.
LOOP AUX2 WHERE LIFNR = AUX1-LIFNR
ENDLOOP.

LOOP AUX3 WHERE LIFNR = AUX1-LIFNR
ENDLOOP.
ENDLOOP.

Además, podrías hacerle un SORT a todas tus tablas por el campo LIFNR antes de hacer los LOOP's e ir borrando los registros ya leídos para ir reduciendo el tamaño de las tablas internas:

SORT: AUX1, AUX2, AUX3 by LIFNR.
LOOP a AUX1.
LOOP a AUX2 WHERE LIFNR = AUX1-LIFNR.
<Realiza operaciones>
DELETE AUX2.
ENDLOOP.

LOOP a AUX3 WHERE LIFNR = AUX1-LIFNR
<Realiza operaciones>
DELETE AUX3.
ENDLOOP.
ENDLOOP.

Y si aún quieres mas velocidad, entónces mete tus tablas y tus work areas en FIELD-SYMBOLS y has los LOOPS con ellos:

FIELD-SYMBOLS: <AUX1> like aux1,
<W_AUX1> like line of aux1,
<AUX2> like aux2,
<W_AUX2> like line of aux2,
<AUX3> like aux3,
<W_AUX3> like line of aux3.

ASSIGN: aux1 TO <AUX1>,
aux2 TO <AUX2>,
aux3 TO <AUX3>.

LOOP AT <AUX1> ASSIGNING <W_AUX1>.
LOOP AT <AUX2> ASSIGNING <W_AUX2>.
<Realiza operaciones>
DELETE <AUX2>.
ENDLOOP.

LOOP AT <AUX3> ASSIGNING <W_AUX3>.
<Realiza operaciones>
DELETE <AUX3>.
ENDLOOP.
ENDLOOP.

Saludos!!!
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Reglas de Mensajes
no puedes crear nuevos temas
no puedes responder temas
no puedes adjuntar archivos
no puedes editar tus mensajes

El código vB está On
Las caritas están On
Código [IMG] está On
Código HTML está Off
Saltar a Foro


Husos Horarios son GMT. La hora en este momento es 15:01:51.


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