Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Seleccion de datos extremadamente lenta... muero esperando.. (https://www.clubdelphi.com/foros/showthread.php?t=96023)

viverosjosem 28-12-2022 04:39:45

Seleccion de datos extremadamente lenta... muero esperando..
 
LLevo muchos anos trabajando con delphi y Paradox. Y ahora me e visto en la necesidad de migrar a SQL. Mi experiencia con SQL, es mas bien pobre.

La situacion es la siguiente:
Tengo un cliente Chino, que tiene una fabrica de masas de hojas de wantan y arrollado primavera.

La tabla de facturas ya tiene casi 19.000 registros.
Los documentos de venta se graban en dos archivos separados: "Facturas" (contiene toda la informacion del docmento de venta: Rut, Numero, Fecha, monto, iva... etc. Cerca de 19.000 registros). Y "DetFact", detalle de facturas. (contiene: Rut, Numero, ademas del detalle de la compra: Codigo, Descripcion, cantidad.., etc. Cerca de 22.000 registros).

Lo que intento hacer, es presentar en un reporte la informacion de los clientes, sus datos de compra, lo adeudado, y los productos adquiridos.


Ejemplo:

Cliente................Factura.......Estado...............Total..........Pagado..........Saldo...... ....Descrip..........................Cantidad
Gin Sam Wan.........12341.....Pendiente........120.000.........80.000........40.000..........Masa Wantan mediano............400



Estoy usando una base de datos SQL Firebird 2.5, con delphi 2010.

Uso el siguiente codigo para hacer la consulta:

Código SQL [-]
         SQLDataSet1.Close;
         SQLDataSet1.CommandType := ctQuery;

         SQL_Text := 'SELECT  ' + 
                              'Facturas.TipoDoc, Facturas.Rut, Facturas.Numero, ' +
                              'Facturas.Estado, '     +
                              'Facturas.FechaEmi, Facturas.FecPago, ' +
                              'Facturas.Total, Facturas.Pagado, Facturas.Saldo, '  +
                              'DetFact.Codigo, DetFact.Descrip, DetFact.Cantidad '  +
                              'Clientes.Nombre, ' +
                      'FROM Facturas '                                 +
                      'LEFT JOIN Clientes '                            +
                      'ON Clientes.Codigo=Facturas.Rut ' +
                      'LEFT JOIN DetFact '                            +
                      'ON DetFact.Rut=Facturas.Rut AND DetFact.Numero=Facturas.Numero  ' +
                      'WHERE ' +
                                 'Facturas.Estado<>' + QuotedStr('A') + ' ' +
                      'ORDER BY Facturas.FechaEmi ' + ';';

   SQLDataSet1.CommandText := SQL_Text;

   SQLDataSet1.Open;
   if ( not SQLDataSet1.Eof ) then begin
     ...
     ...
     Lineas de codigo para el reporte..
     ...


El problema es, que esta consulta se demora mas de 10 minutos en arrojar resultados.

Existe alguna manera de hacer esto distinto?, para que la consulta sea mas rapida, sino automatica?.

Saludos.

Gracias de antemano.

Jose Miguel B.

Neftali [Germán.Estévez] 28-12-2022 09:15:33

Lo primero que haría sería revisar el plan de ejecución a ver en qué se está "perdiendo" ese tiempo.
No parece una consulta lo bastante compleja para que el Open tarde 10 minutos.

A partir de lo que diga el plan de ejecución se puede ver qué hacer exactamente.

De todas formas puedes revisar que:
  • Las tablas tengan los índices correspondientes, sobre todo por los campos por los que haces JOIN
  • Revisa si las LEFT JOIN, puedes convertirlas en INNER JOIN
  • Prueba a utilizar cursor unidireccional y/o sólo lectura en el Dataset (Query). Si tienes la propiedad y si te sirve para el listado.
He asumido que lo que tarda es el Ooen, pero deberías asegurarte de que no sea el While el que está consumiendo el tiempo.

duilioisola 28-12-2022 09:52:11

Asegúrate de que los índices son los que necesitas.
Esto es en base al SQL que ejecutas, aunque creo que quizás falten más cosas.
  • No utilizas TIPODOC en el WHERE
  • TIPODOC debería estar también en el detalle si es parte de la PK de FACTURAS

Código SQL [-]
CREATE TABLE FACTURAS (
    NUMERO    INTEGER NOT NULL,
    RUT       VARCHAR(15) NOT NULL,
    TIPODOC   VARCHAR(15),
    ESTADO    INTEGER,
    FECHAEMI  DATE,
    FECPAGO   DATE,
    TOTAL     DOUBLE PRECISION,
    PAGADO    SMALLINT,
    SALDO     DOUBLE PRECISION
    /*
    ...
    */
);

ALTER TABLE FACTURAS ADD CONSTRAINT PK_FACTURAS PRIMARY KEY (NUMERO, RUT);

/* Para la parte WHERE FACTURAS.ESTADO <> :ESTADO */
CREATE INDEX FACTURAS_IDX1 ON FACTURAS (ESTADO);

CREATE TABLE DETFACT (
    NUMERO    INTEGER NOT NULL,
    RUT       VARCHAR(15) NOT NULL,
    LINEA     INTEGER NOT NULL,
    CODIGO    VARCHAR(15),
    DESCRIP   VARCHAR(60),
    CANTIDAD  INTEGER
    /*
    ...
    */
);

ALTER TABLE DETFACT ADD CONSTRAINT PK_DETFACT PRIMARY KEY (NUMERO, RUT, LINEA);

/* Puede ser una Foreign Key o un índice */
/* Para el join: ON DETFACT.RUT = FACTURAS.RUT AND DETFACT.NUMERO = FACTURAS.NUMERO */
ALTER TABLE DETFACT ADD CONSTRAINT FK_DETFACT_1 FOREIGN KEY (NUMERO, RUT) REFERENCES FACTURAS (NUMERO, RUT);


CREATE TABLE CLIENTES (
    CODIGO  VARCHAR(15) NOT NULL,
    NOMBRE  VARCHAR(60)
    /*
    ...
    */
);

/* Para el join: ON CLIENTES.CODIGO = FACTURAS.RUT */
ALTER TABLE CLIENTES ADD CONSTRAINT PK_CLIENTES PRIMARY KEY (CODIGO);

Código SQL [-]
SELECT FACTURAS.TIPODOC, FACTURAS.RUT, FACTURAS.NUMERO, FACTURAS.ESTADO, FACTURAS.FECHAEMI, FACTURAS.FECPAGO,
       FACTURAS.TOTAL, FACTURAS.PAGADO, FACTURAS.SALDO, DETFACT.CODIGO, DETFACT.DESCRIP, DETFACT.CANTIDAD,
       CLIENTES.NOMBRE
FROM FACTURAS
LEFT JOIN CLIENTES ON CLIENTES.CODIGO = FACTURAS.RUT
LEFT JOIN DETFACT ON DETFACT.RUT = FACTURAS.RUT AND DETFACT.NUMERO = FACTURAS.NUMERO
WHERE
FACTURAS.ESTADO <> :ESTADO
ORDER BY FACTURAS.FECHAEMI


Si presentas la estructura completa de estas tres tablas quizás podamos ayudarte un poco más.

viverosjosem 28-12-2022 10:49:08

Hola a todos.
Agradesco el tiempo y la molestia que se han tomado para contestar.

Duilioisola, tienes razon. Diste en el clavo. ^\||/
Cita:

TIPODOC debería estar también en el detalle si es parte de la PK de FACTURAS".
Pase por alto el campo "TipoDoc", en el detalle de Facturas. Lo e incorporado, y ahora la consulta es automatica.

Muchas gracias por sus respuestas.

Saludos.
Jose Miguel.


La franja horaria es GMT +2. Ahora son las 06:39:19.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi