Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 16-05-2014
Avatar de Caminante
Caminante Caminante is offline
Miembro
 
Registrado: oct 2010
Ubicación: Lima - Peru
Posts: 338
Poder: 14
Caminante Va camino a la fama
Red face Dudas con esta consulta

Buenos dias, tardes o noches segun corresponda. Tengo una duda que espero puedan ayudarme a despejar.
Tengo un sistema funcionando en firebird 2.5. En este tengo un listado de resumen. La consulta que lanzo es la siguiente:

Código SQL [-]
SELECT MC.ID_MOV, DC.ID_DETCIL, MC.FECHADOC, DC.CIL,CI.TIPOGASID, TG.TIPOGAS,
CI.DESCRIPCION,CI.CAPACIDAD, MC.SERIE, MC.DOCUMENTO,DC.PLAZO,
DC.FECHADEV, DC.DOCDEV,MC.NOMDESTINO, CP1.NOMBRE,CP2.ID_CLIENTE,
CP2.TIPO, CP2.NOMBRE,DC.LUGAR, DC.OBSERVACION FROM
DETALLECIL DC INNER JOIN MOVCILINDROS MC ON DC.MOVCIL=MC.ID_MOV
INNER JOIN CILINDROS CI on DC.CIL=CI.ID_CILINDRO INNER JOIN
CLIEPROV CP1 ON MC.NOMDESTINO=CP1.ID_CLIENTE INNER JOIN
CLIEPROV CP2 ON CI.PROPIETARIO=CP2.ID_CLIENTE
INNER JOIN TIPOGASES TG ON CI.tipogasid=TG.id
WHERE CP1.id_cliente>0
La consulta en si me da los resultados esperados con una demora maxima de un par de segundos. Ahora revisando en los foros escuche mencionar el IB plan analizer para analizar las consultas. Lo probe y me salio en las tablaS MOVCILINDROS Y DETALLECIL una advertencia. Revisando veo que utiliza los indices que corresponde a sus respectivas claves foraneas.
Este es el plan usado:

Código SQL [-]
PLAN JOIN (CP1 INDEX (RDB$PRIMARY2), MC INDEX (RDB$FOREIGN5), DC INDEX (RDB$FOREIGN12), CI INDEX (RDB$PRIMARY1), CP2 INDEX (RDB$PRIMARY2), TG INDEX (PK_TIPOGASES))

Estas son las tablas usadas:

Código SQL [-]
CREATE TABLE CILINDROS (
    ID_CILINDRO  INTEGER NOT NULL,
    DESCRIPCION  VARCHAR(30),
    TIPOGASID    INTEGER NOT NULL,
    CAPACIDAD    VARCHAR(7),
    PROPIETARIO  INTEGER,
    OBSCILINDRO  VARCHAR(30)
);

CREATE TABLE CLIEPROV (
    ID_CLIENTE  INTEGER NOT NULL,
    RUC         VARCHAR(11),
    NOMBRE      TCADENA NOT NULL COLLATE ES_ES_CI_AI,
    EMAIL       VARCHAR(30),
    WEB         VARCHAR(30),
    CONTACTO    VARCHAR(50),
    TIPO        INTEGER NOT NULL,
    NOMMAYUS    TCADENA COLLATE ES_ES_CI_AI,
    RUBRO       TRUBRO NOT NULL
);

CREATE TABLE DETALLECIL (
    ID_DETCIL    INTEGER NOT NULL,
    MOVCIL       INTEGER NOT NULL,
    CIL          INTEGER NOT NULL,
    PLAZO        INTEGER DEFAULT 0,
    FECHADEV     DATE,
    OBSERVACION  VARCHAR(50),
    DOCDEV       VARCHAR(15),
    LUGAR        VARCHAR(15)
);

CREATE TABLE MOVCILINDROS (
    ID_MOV      INTEGER NOT NULL,
    NOMDESTINO  INTEGER NOT NULL,
    SERIE       VARCHAR(3) NOT NULL,
    DOCUMENTO   VARCHAR(10) NOT NULL,
    FECHADOC    DATE NOT NULL,
    VENDEDOR    INTEGER NOT NULL
);

CREATE TABLE TIPOGASES (
    ID       INTEGER NOT NULL,
    TIPOGAS  VARCHAR(10) NOT NULL COLLATE ES_ES_CI_AI
);

ALTER TABLE CILINDROS ADD PRIMARY KEY (ID_CILINDRO);
ALTER TABLE CLIEPROV ADD PRIMARY KEY (ID_CLIENTE);
ALTER TABLE DETALLECIL ADD PRIMARY KEY (ID_DETCIL);
ALTER TABLE MOVCILINDROS ADD PRIMARY KEY (ID_MOV);
ALTER TABLE TIPOGASES ADD CONSTRAINT PK_TIPOGASES PRIMARY KEY (ID);

ALTER TABLE CILINDROS ADD CONSTRAINT FK_CILINDROS_1 FOREIGN KEY (TIPOGASID) REFERENCES TIPOGASES (ID) ON UPDATE CASCADE;
ALTER TABLE CILINDROS ADD FOREIGN KEY (PROPIETARIO) REFERENCES CLIEPROV (ID_CLIENTE) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE DETALLECIL ADD CONSTRAINT FKDETALLECIL_CIL FOREIGN KEY (CIL) REFERENCES CILINDROS (ID_CILINDRO) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE DETALLECIL ADD FOREIGN KEY (MOVCIL) REFERENCES MOVCILINDROS (ID_MOV) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE MOVCILINDROS ADD CONSTRAINT FK_MOVCILINDROS_DEST FOREIGN KEY (NOMDESTINO) REFERENCES CLIEPROV (ID_CLIENTE) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE MOVCILINDROS ADD FOREIGN KEY (VENDEDOR) REFERENCES PERSONAL (ID_PERSONAL) ON DELETE NO ACTION ON UPDATE CASCADE;
Si bien la consulta no es lenta (Al menos no mucho). Me preocupa que no este debidamente optimizada. Viendo las estadisticas de los indices se muestra la siguiente selectividad:

RDB$FOREIGN5 24.59
RDB$FOREIGN12 2.48

Me pregunto ¿De que manera se puede mejorar esta consulta?

Gracias por la atención prestada...
Responder Con Cita
  #2  
Antiguo 16-05-2014
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.735
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Dado que el WHERE actúa sobre la tabla "CLIEPROV CP1" yo trataría de empezar por ahí las uniones con las otras tablas.

Código SQL [-]
SELECT MC.ID_MOV, DC.ID_DETCIL, MC.FECHADOC, DC.CIL,CI.TIPOGASID, TG.TIPOGAS,
CI.DESCRIPCION,CI.CAPACIDAD, MC.SERIE, MC.DOCUMENTO,DC.PLAZO,
DC.FECHADEV, DC.DOCDEV,MC.NOMDESTINO, CP1.NOMBRE,CP2.ID_CLIENTE,
CP2.TIPO, CP2.NOMBRE,DC.LUGAR, DC.OBSERVACION
FROM
CLIEPROV CP1
JOIN MOVCILINDROS MC ON MC.NOMDESTINO=CP1.ID_CLIENTE
JOIN DETALLECIL DC ON DC.MOVCIL=MC.ID_MOV
JOIN CILINDROS CI ON DC.CIL=CI.ID_CILINDRO
JOIN CLIEPROV CP2 ON CI.PROPIETARIO=CP2.ID_CLIENTE
JOIN TIPOGASES TG ON CI.tipogasid=TG.id
WHERE
CP1.ID_CLIENTE > 0

Además de esto probaría la consulta utilizando LEFT JOIN.


Los índices que utiliza aparentemente son los correctos y parecen óptimos.
Código SQL [-]
CLIEPROV CP1
JOIN MOVCILINDROS MC ON MC.NOMDESTINO=CP1.ID_CLIENTE
ALTER TABLE MOVCILINDROS ADD CONSTRAINT FK_MOVCILINDROS_DEST FOREIGN KEY (NOMDESTINO) REFERENCES CLIEPROV (ID_CLIENTE) ON DELETE NO ACTION ON UPDATE CASCADE;
y
Código SQL [-]
JOIN DETALLECIL DC ON DC.MOVCIL=MC.ID_MOV
ALTER TABLE DETALLECIL ADD FOREIGN KEY (MOVCIL) REFERENCES MOVCILINDROS (ID_MOV) ON DELETE CASCADE ON UPDATE CASCADE;
Responder Con Cita
  #3  
Antiguo 16-05-2014
Avatar de Caminante
Caminante Caminante is offline
Miembro
 
Registrado: oct 2010
Ubicación: Lima - Peru
Posts: 338
Poder: 14
Caminante Va camino a la fama
Hola gracias por responder
Cita:
Empezado por duilioisola Ver Mensaje
Además de esto probaría la consulta utilizando LEFT JOIN.
Y Como seria la consulta??

He probado asi:

Código SQL [-]
SELECT MC.ID_MOV, DC.ID_DETCIL, MC.FECHADOC, DC.CIL,CI.TIPOGASID, TG.TIPOGAS,
CI.DESCRIPCION,CI.CAPACIDAD, MC.SERIE, MC.DOCUMENTO,DC.PLAZO,
DC.FECHADEV, DC.DOCDEV,MC.NOMDESTINO, CP1.NOMBRE,CP2.ID_CLIENTE,
CP2.TIPO, CP2.NOMBRE,DC.LUGAR, DC.OBSERVACION FROM
DETALLECIL DC left JOIN MOVCILINDROS MC ON DC.MOVCIL=MC.ID_MOV
INNER JOIN CILINDROS CI on DC.CIL=CI.ID_CILINDRO INNER JOIN
CLIEPROV CP1 ON MC.NOMDESTINO=CP1.ID_CLIENTE INNER JOIN
CLIEPROV CP2 ON CI.PROPIETARIO=CP2.ID_CLIENTE
INNER JOIN TIPOGASES TG ON CI.tipogasid=TG.id
WHERE CP1.id_cliente>0 and dc.id_detcil>0

Y ahora si parece estar todo ok con los indices. Pero la demora es la misma.
Responder Con Cita
  #4  
Antiguo 17-05-2014
Avatar de Caminante
Caminante Caminante is offline
Miembro
 
Registrado: oct 2010
Ubicación: Lima - Peru
Posts: 338
Poder: 14
Caminante Va camino a la fama
Ahora el nuevo plan es este:

Código SQL [-]
PLAN JOIN (JOIN (JOIN (DC INDEX (RDB$PRIMARY4), MC INDEX (RDB$PRIMARY6)), CI INDEX (RDB$PRIMARY1), CP1 INDEX (RDB$PRIMARY2)), CP2 INDEX (RDB$PRIMARY2), TG INDEX (PK_TIPOGASES))
Responder Con Cita
  #5  
Antiguo 17-05-2014
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.735
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Prueba con la que te propuse, reordenando los joins y agregando left delante de cada uno:
Código SQL [-]
SELECT MC.ID_MOV, DC.ID_DETCIL, MC.FECHADOC, DC.CIL,CI.TIPOGASID, TG.TIPOGAS,
CI.DESCRIPCION,CI.CAPACIDAD, MC.SERIE, MC.DOCUMENTO,DC.PLAZO,
DC.FECHADEV, DC.DOCDEV,MC.NOMDESTINO, CP1.NOMBRE,CP2.ID_CLIENTE,
CP2.TIPO, CP2.NOMBRE,DC.LUGAR, DC.OBSERVACION
FROM
CLIEPROV CP1
LEFT JOIN MOVCILINDROS MC ON MC.NOMDESTINO=CP1.ID_CLIENTE
LEFT JOIN DETALLECIL DC ON DC.MOVCIL=MC.ID_MOV
LEFT JOIN CILINDROS CI ON DC.CIL=CI.ID_CILINDRO
LEFT JOIN CLIEPROV CP2 ON CI.PROPIETARIO=CP2.ID_CLIENTE
LEFT JOIN TIPOGASES TG ON CI.tipogasid=TG.id
WHERE
CP1.ID_CLIENTE > 0
Responder Con Cita
  #6  
Antiguo 17-05-2014
Avatar de Caminante
Caminante Caminante is offline
Miembro
 
Registrado: oct 2010
Ubicación: Lima - Peru
Posts: 338
Poder: 14
Caminante Va camino a la fama
Hola de nuevo

Cita:
Empezado por duilioisola Ver Mensaje
WHERE
CP1.ID_CLIENTE > 0
[/sql]
Bueno esta linea realmente no es necesaria. Solo la puse siguiendo un consejo de internet para obligar a utilizar un indice en el plan (Ya que daba natural join cp1 cuando no estaba esa linea).


Ya probe como me dijiste pero igual sigue con ese detalle en los mismos indices.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

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

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Ayuda con esta consulta jfbaez SQL 5 18-05-2010 17:33:21
dudas en una consulta con sql rufo SQL 2 06-01-2010 18:05:09
Dudas con consulta SQL Rach Peguero Tablas planas 6 02-01-2008 15:38:28
Está bien esta consulta Select count? enecumene MySQL 12 30-08-2007 03:54:29
Dudas Con Una Consulta bustio Varios 3 26-01-2005 08:38:47


La franja horaria es GMT +2. Ahora son las 16:10:29.


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
Copyright 1996-2007 Club Delphi