Consulta entre varias tablas, como optimizar los tiempos

1,100 views
Skip to first unread message

alejandro

unread,
Dec 15, 2015, 12:47:32 PM12/15/15
to Comunidad de Visual Foxpro en Español
Buenas tardes, vengo teniendo problemas en el rendimiento de una aplicación armada en visual foxpro 9 sp2 y bases de datos nativas.
Tengo varias tablas relacionadas por codigos primarios y secundarios, me encuentro con el problema de tener que bajar los tiempos para una consulta multiple que relaciona a todas las tablas, aca paso el codigo haber si se puede optimizar

SELECT M.CodVenta, M.CodProducto, M.Cantidad FROM VentasC as V INNER JOIN MovVentas as M ON V.CodVenta= M.CodVenta;
WHERE (TTOD(V.fecha)>= VDesde AND TTOD(V.Fecha)<= VHasta) AND (M.IdProducto in(SELECT P.IdProducto FROM Productos as P WHERE P.IdProveedo= 60 AND P.IdRubro in(SELECT R.IdRubro FROM Rubros as R WHERE R.Descripcion != VRubro)))INTO CURSOR RR readwrite

select RR
  Sum Cantidad for CodVenta>0 to LaCantidad

thisform.TxtCantidad= RR.LaCantidad

Desde ya muchísimas gracias..

Víctor Hugo Espínola Domínguez

unread,
Dec 15, 2015, 7:40:14 PM12/15/15
to publice...@googlegroups.com
Prueba si arroja el mismo resultado:

Select  mov.CodVenta   ;
 , mov.CodProducto   ;
 , mov.Cantidad   ;
From VentasC As vta   ;
Inner Join MovVentas As mov   ;
On vta.CodVenta = mov.CodVenta   ;
Inner Join Productos As pro   ;
On mov.IdProducto = pro.IdProducto           ;
Inner Join Rubros As rub   ;
On pro.IdRubro = rub.IdRubro   ;
Where rub.Descripcion <> m.VRubro   ;
And Between(Ttod(vta.fecha), m.VDesde, m.VHasta)      ;
And pro.IdProveedo = 60   ;
Into Cursor RR Readwrite


Saludos,
Víctor.
Lambaré - Paraguay.

Carlos Miguel FARIAS

unread,
Dec 16, 2015, 6:20:54 AM12/16/15
to Grupo Fox
a) En lugar de verificar el rango de la fecha con la doble comparación o con la función BETWEEN, usaría la clausula BETWEEN de SQL.
Una clausula BETWEEN permite a rushmore optimizar el filtro por fecha, ya que es algo de "él", y si sobre el campo fecha agregamos un índice (sin activarlo) mejor desempeño.
b) En lugar de convertir vta.fecha a date, dentro del SQL, convertiría a vDesde y VHasta a datetime, antes de empezar la consulta. De esa manera, evito que cada vez que lee un registro, se tenga que convertir la fecha de la tabla (DOS VECES por cada registro), de la otra manera, solo son dos conversiones en total, es más, ruhsmore no podría optimizar el filtro sobre una fecha "envuelta" dentro de una función
c) Si el cursor no se va a modificar, no crearlo como readwrite

ejemplos:
Primera aproximación
tDesde = DTOT(vDesde)
tHasta = DTOC(VHasta)
SELECT M.CodVenta, M.CodProducto, M.Cantidad;
   FROM VentasC as V INNER JOIN MovVentas as M ON V.CodVenta= M.CodVenta;
   WHERE V.fecha BETWEEN tDesde AND tHasta AND;
   M.IdProducto IN(SELECT IdProducto FROM Productos AS P;
                    WHERE P.IdProveedo=60 AND;
                          P.IdRubro IN(SELECT R.IdRubro FROM Rubros as R;
                                        WHERE R.Descripcion != VRubro)));
   INTO CURSOR RR READWRITE

Pero como hay sub consultas anidadas, me parece más simple crear un curso intermedio para las subconsultas, y luego filtrar contra ese cursor (lo que si podrá ser optimizado).
Segunda aproximación.

tDesde = DTOT(vDesde)
tHasta = DTOC(VHasta)
SELECT IdProducto FROM Productos;
   WHERE IdProveedo=60 AND;
         IdRubro IN(SELECT IdRubro FROM Rubros WHERE Descripcion != VRubro);
   INTO CURSOR ProdProv60segunRubro

SELECT M.CodVenta, M.CodProducto, M.Cantidad;
   FROM VentasC as V INNER JOIN MovVentas as M ON V.CodVenta= M.CodVenta;
   WHERE V.fecha BETWEEN tDesde AND tHasta AND;
         M.IdProducto IN(SELECT IdProducto FROM ProdProv60segunRubro);
   INTO CURSOR RR READWRITE

De esta manera, circula menor cantidad de datos por la red, o en todo caso, no trae todos los datos a la vez. Siempre que se quiera optimizar una consulta SQL SELECT, hay que entender que es una sentencia naturalmente "bucle", o sea, hace un proceso repetitivo.
Entonces, en base a dicho entendimiento, como cualquier buen programador sabe, todo lo que no se modifica dentro de un bucle, debe sacarse fuera de él.
En este caso, algo fijo de afuera (los límites de fecha como limites), exige convertir dentro del bucle en forma repetida el campo fecha-hora, entonces, convierto a fecha-hora afuera y no necesito convertir, en cada registro, el dato de la tabla.
Y otra optimización es usar dentro del SQL, la mayor cantidad de clausulas propias del SQL, la función BETWEEN(), no es propia del SQL, es una función del Fox, no se en cuanto podrá afectar el desempeño de la consulta (Victor, logra si, reducir las conversiones del campo fecha a 1 sola contra dos de la original).
Saludos: Miguel, La Pampa (RA)

Larga Vida y Prosperidad
Que la Fuerza les acompañe, sobre todo si aparece "el oscuro de la fuerza"


alejandro

unread,
Dec 16, 2015, 3:24:57 PM12/16/15
to Comunidad de Visual Foxpro en Español
Excelentee solución!!! muchísimas gracias por el tiempo que gastaron en explicarme Victor Hugo y Miguel.
El codigo que me paso miguel me bajo el tiempo en un porcentaje altísimo!!!!
Muchas muchas gracias!!!!
Reply all
Reply to author
Forward
0 new messages