Ir al contenido


Foto

Dudas con esta consulta


  • Por favor identifícate para responder
5 respuestas en este tema

#1 Caminante21

Caminante21

    Member

  • Miembros
  • PipPip
  • 21 mensajes
  • LocationLima, Peru

Escrito 16 mayo 2014 - 05:41

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:



delphi
  1. SELECT MC.ID_MOV, DC.ID_DETCIL, MC.FECHADOC, DC.CIL,CI.TIPOGASID, TG.TIPOGAS,
  2. CI.DESCRIPCION,CI.CAPACIDAD, MC.SERIE, MC.DOCUMENTO,DC.PLAZO,
  3. DC.FECHADEV, DC.DOCDEV,MC.NOMDESTINO, CP1.NOMBRE,CP2.ID_CLIENTE,
  4. CP2.TIPO, CP2.NOMBRE,DC.LUGAR, DC.OBSERVACION FROM
  5. DETALLECIL DC INNER JOIN MOVCILINDROS MC ON DC.MOVCIL=MC.ID_MOV
  6. INNER JOIN CILINDROS CI on DC.CIL=CI.ID_CILINDRO INNER JOIN
  7. CLIEPROV CP1 ON MC.NOMDESTINO=CP1.ID_CLIENTE INNER JOIN
  8. CLIEPROV CP2 ON CI.PROPIETARIO=CP2.ID_CLIENTE
  9. INNER JOIN TIPOGASES TG ON CI.tipogasid=TG.id
  10. 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:



delphi
  1. 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:



delphi
  1. CREATE TABLE CILINDROS (
  2.     ID_CILINDRO  INTEGER NOT NULL,
  3.     DESCRIPCION  VARCHAR(30),
  4.     TIPOGASID    INTEGER NOT NULL,
  5.     CAPACIDAD    VARCHAR(7),
  6.     PROPIETARIO  INTEGER,
  7.     OBSCILINDRO  VARCHAR(30)
  8. );
  9.  
  10. CREATE TABLE CLIEPROV (
  11.     ID_CLIENTE  INTEGER NOT NULL,
  12.     RUC        VARCHAR(11),
  13.     NOMBRE      TCADENA NOT NULL COLLATE ES_ES_CI_AI,
  14.     EMAIL      VARCHAR(30),
  15.     WEB        VARCHAR(30),
  16.     CONTACTO    VARCHAR(50),
  17.     TIPO        INTEGER NOT NULL,
  18.     NOMMAYUS    TCADENA COLLATE ES_ES_CI_AI,
  19.     RUBRO      TRUBRO NOT NULL
  20. );
  21.  
  22. CREATE TABLE DETALLECIL (
  23.     ID_DETCIL    INTEGER NOT NULL,
  24.     MOVCIL      INTEGER NOT NULL,
  25.     CIL          INTEGER NOT NULL,
  26.     PLAZO        INTEGER DEFAULT 0,
  27.     FECHADEV    DATE,
  28.     OBSERVACION  VARCHAR(50),
  29.     DOCDEV      VARCHAR(15),
  30.     LUGAR        VARCHAR(15)
  31. );
  32.  
  33. CREATE TABLE MOVCILINDROS (
  34.     ID_MOV      INTEGER NOT NULL,
  35.     NOMDESTINO  INTEGER NOT NULL,
  36.     SERIE      VARCHAR(3) NOT NULL,
  37.     DOCUMENTO  VARCHAR(10) NOT NULL,
  38.     FECHADOC    DATE NOT NULL,
  39.     VENDEDOR    INTEGER NOT NULL
  40. );
  41.  
  42. CREATE TABLE TIPOGASES (
  43.     ID      INTEGER NOT NULL,
  44.     TIPOGAS  VARCHAR(10) NOT NULL COLLATE ES_ES_CI_AI
  45. );
  46.  
  47. ALTER TABLE CILINDROS ADD PRIMARY KEY (ID_CILINDRO);
  48. ALTER TABLE CLIEPROV ADD PRIMARY KEY (ID_CLIENTE);
  49. ALTER TABLE DETALLECIL ADD PRIMARY KEY (ID_DETCIL);
  50. ALTER TABLE MOVCILINDROS ADD PRIMARY KEY (ID_MOV);
  51. ALTER TABLE TIPOGASES ADD CONSTRAINT PK_TIPOGASES PRIMARY KEY (ID);
  52.  
  53. ALTER TABLE CILINDROS ADD CONSTRAINT FK_CILINDROS_1 FOREIGN KEY (TIPOGASID) REFERENCES TIPOGASES (ID) ON UPDATE CASCADE;
  54. ALTER TABLE CILINDROS ADD FOREIGN KEY (PROPIETARIO) REFERENCES CLIEPROV (ID_CLIENTE) ON DELETE NO ACTION ON UPDATE CASCADE;
  55. ALTER TABLE DETALLECIL ADD CONSTRAINT FKDETALLECIL_CIL FOREIGN KEY (CIL) REFERENCES CILINDROS (ID_CILINDRO) ON DELETE NO ACTION ON UPDATE CASCADE;
  56. ALTER TABLE DETALLECIL ADD FOREIGN KEY (MOVCIL) REFERENCES MOVCILINDROS (ID_MOV) ON DELETE CASCADE ON UPDATE CASCADE;
  57. ALTER TABLE MOVCILINDROS ADD CONSTRAINT FK_MOVCILINDROS_DEST FOREIGN KEY (NOMDESTINO) REFERENCES CLIEPROV (ID_CLIENTE) ON DELETE NO ACTION ON UPDATE CASCADE;
  58. 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 atencion prestada...
  • 0

#2 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.092 mensajes
  • LocationMurcia, España

Escrito 16 mayo 2014 - 11:44

Usa como tabla principal (en el FROM) aquella que luego vayas a filtrar (en el WHERE, CPl en tu caso) en lugar de filtrar por algo que está en un join.

Cambiando solo esto podrías bajar mucho de tiempos, en algunos casos reales se divide hasta por 100!
  • 0

#3 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 16 mayo 2014 - 12:26

Usa como tabla principal (en el FROM) aquella que luego vayas a filtrar (en el WHERE, CPl en tu caso) en lugar de filtrar por algo que está en un join.

Cambiando solo esto podrías bajar mucho de tiempos, en algunos casos reales se divide hasta por 100!


Seguro, certifico que lo que comenta nuestro amigo Sergio es una realidad y te ahorras mucho mucho tiempo en las consultas.

saludos

PD, Si Si, a mi me pasó y que y que  :D :D :D
  • 0

#4 Caminante21

Caminante21

    Member

  • Miembros
  • PipPip
  • 21 mensajes
  • LocationLima, Peru

Escrito 16 mayo 2014 - 12:43

Gracias por responder



delphi
  1. WHERE CP1.id_cliente>0



Esa linea ya tenia tiempo recuerdo que cuando no estaba el plan me marcaba un natural join (o algo asi) en la tabla cp1. Y al agregar esa linea ya utilizaba el indice.

Pero ahora la quite para ver que ademas de tardar unos milisegundos mas salia en el plan analizer
un icono de stop en el indice FK_cilindros_1 de la tabla CI con una selectividad de 1852.5.



  • 0

#5 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.092 mensajes
  • LocationMurcia, España

Escrito 19 mayo 2014 - 01:43

Al final la idea es que la tablas que más trabajo tenga, esa ha de ir en el SELECT, si hay un where suele ser esa, y si no, pues si la conslta al final es de factura,s por la tabla de facturas la primera, esa es la idea y se consigue mucha velocidad.
  • 0

#6 Caminante21

Caminante21

    Member

  • Miembros
  • PipPip
  • 21 mensajes
  • LocationLima, Peru

Escrito 19 mayo 2014 - 08:50

Gracias creo que ya voy a entendiendo la manera de manejar mejor las consultas.
  • 0




IP.Board spam blocked by CleanTalk.