1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

HELP to optimize a query

Discussion in 'Databases' started by amota, Jun 1, 2006.

  1. #1
    Hi,
    I have a query to consult several tables. It works but it's too slow!
    I need to do it faster! Please, someone helps me.

    TABLE DEFINITIONS:

    CREATE TABLE `importaciones` (
    `idcliente` varchar(13) NOT NULL default '',
    `pedido` varchar(20) default NULL,
    `producto` varchar(255) default NULL,
    `do` varchar(12) NOT NULL default '',
    `fec_actual` date default NULL,
    `ciudad` varchar(20) default NULL,
    `razon` varchar(255) default NULL,
    `tabla` char(1) default 'I',
    PRIMARY KEY (`do`),
    KEY `do` (`do`),
    KEY `pedido` (`pedido`),
    KEY `horas` (`horas`),
    KEY `ciudad` (`ciudad`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

    CREATE TABLE `exportaciones` (
    `idcliente` varchar(13) default NULL,
    `do` varchar(15) NOT NULL default '',
    `pedido` varchar(15) default NULL,
    `ciudad` varchar(50) default NULL,
    `producto` text,
    `razon` varchar(255) default NULL,
    `tabla` char(1) default 'E',
    PRIMARY KEY (`do`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

    CREATE TABLE `plantilla` (
    `id` int(7) NOT NULL auto_increment,
    `idproceso` tinyint(4) default NULL,
    `idactividad` varchar(5) default NULL,
    `desc_actividad` varchar(255) default NULL,
    PRIMARY KEY (`id`),
    KEY `idproceso` (`idproceso`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

    CREATE TABLE `procesos` (
    `idproceso` tinyint(4) NOT NULL default '0',
    `nombre` varchar(30) default NULL,
    `nombrecorto` varchar(10) default NULL,
    PRIMARY KEY (`idproceso`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

    CREATE TABLE `estadohechos` (
    `regn` mediumint(8) unsigned NOT NULL auto_increment,
    `numdo` varchar(8) NOT NULL default '',
    `etapa` varchar(4) NOT NULL default '',
    `fecha` date NOT NULL default '0000-00-00',
    `hora` time NOT NULL default '00:00:00',
    `tipo` tinyint(2) NOT NULL default '0' COMMENT 'Si es interrupción o normal',
    `regusu` mediumint(6) unsigned NOT NULL default '0',
    `observaciones` text NOT NULL,
    `flag` char(1) NOT NULL default '',
    `sede` tinyint(3) default NULL COMMENT '1=Ctg,2=Barr,3=Bog,4=Bvt',
    `grabado` timestamp NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
    PRIMARY KEY (`regn`),
    KEY `PorInterrup` (`numdo`,`etapa`,`tipo`),
    KEY `PorNumDO` (`numdo`,`etapa`,`fecha`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;

    CREATE TABLE `ordenes` (
    `regn` mediumint(8) NOT NULL auto_increment,
    `proceso` tinyint(4) NOT NULL default '0',
    `numdo` varchar(8) NOT NULL default '',
    `nitcliente` varchar(11) NOT NULL default '',
    `terminado` tinyint(1) NOT NULL default '0',
    PRIMARY KEY (`regn`),
    UNIQUE KEY `PorNumDO` (`proceso`,`numdo`),
    KEY `PorNitCliente` (`proceso`,`nitcliente`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;

    CREATE TABLE `etapas` (
    `regn` smallint(5) unsigned NOT NULL auto_increment,
    `proceso` tinyint(4) NOT NULL default '0',
    `tipo` tinyint(4) NOT NULL default '0',
    `codigo` char(4) NOT NULL default '',
    `descripcion` char(30) NOT NULL default '',
    PRIMARY KEY (`regn`),
    KEY `PorEtapa` (`proceso`,`tipo`,`codigo`),
    KEY `descripcion` (`descripcion`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED;


    THE QUERY I NEED TO DO FASTER:

    SELECT * FROM
    (SELECT distinct `procesos`.`nombrecorto`, `importaciones`.`idcliente`, `importaciones`.`pedido`, `importaciones`.`razon`, `importaciones`.`do`, `importaciones`.`fec_actual`, `importaciones`.`producto`, `importaciones`.`ciudad`, `importaciones`.`tabla`,
    (select et.descripcion from etapas et, estadohechos es
    where es.etapa = et.codigo and `ordenes`.numdo=es.numdo
    and et.descripcion <> 'ANULADO'
    order by fecha,hora desc limit 1) AS estado,
    (select et.descripcion from etapas et, estadohechos es
    where es.etapa = et.codigo and `ordenes`.numdo=es.numdo
    and et.descripcion <> 'ANULADO'
    and et.codigo in
    (select plantilla.idactividad from plantilla
    where asercol.idproceso = ordenes.proceso)
    order by fecha,hora desc limit 1) AS estado_as,
    `ordenes`.`proceso`,
    ordenes.terminado
    FROM `importaciones`, ordenes, procesos, estadohechos
    where (`importaciones`.`do` = `ordenes`.`numdo` and
    `ordenes`.`proceso` = `procesos`.`idproceso` and
    `importaciones`.`do` = estadohechos.`numdo` )
    UNION
    SELECT distinct `procesos`.`nombrecorto`, `exportaciones`.`idcliente`, `exportaciones`.`pedido`, `exportaciones`.`razon`, `exportaciones`.`do`, `asercol`.`exportaciones`.`fec_actual`, `exportaciones`.`producto`, `exportaciones`.`ciudad`, `exportaciones`.`tabla`,
    (select et.descripcion from etapas et, estadohechos es
    where es.etapa = et.codigo and `ordenes`.numdo=es.numdo
    and et.descripcion <> 'ANULADO'
    order by fecha,hora desc limit 1) AS etapa,
    (select et.descripcion from etapas et, estadohechos es
    where es.etapa = et.codigo and `ordenes`.numdo=es.numdo
    and et.descripcion <> 'ANULADO'
    and et.codigo in
    (select plantilla.idactividad from plantilla
    where plantilla.idproceso = ordenes.proceso)
    order by fecha,hora desc limit 1) AS etapa_as,
    `ordenes`.`proceso`,
    ordenes.terminado as finalizado
    FROM `exportaciones`, ordenes, procesos, estadohechos
    where
    `exportaciones`.`do` = `ordenes`.`numdo` and
    `ordenes`.`proceso` = `procesos`.`idproceso` and
    `exportaciones`.`do` = estadohechos.`numdo`
    ) AS TABLA[/COLOR]


    In words, what I need is:
    - all of the records from importaciones
    - all of the records from exportaciones
    Additional information found in:
    - ordenes: 'proceso' - the short name which is in 'procesos'
    'terminado'
    - estadohechos-etapas: description of last 'etapa' done to 'do' (pk)

    The thing is, my php application gets a timeout, so I can't execute this query.
    Any help will be really appreciated!!!

    Attached is the EXPLAIN Query result.
     

    Attached Files:

    amota, Jun 1, 2006 IP
  2. Dan Grossman

    Dan Grossman Peon

    Messages:
    177
    Likes Received:
    8
    Best Answers:
    0
    Trophy Points:
    0
    #2
    Wow. A bit too much like work.. to optimize it for free =p
     
    Dan Grossman, Jun 2, 2006 IP
  3. sadcox66

    sadcox66 Spirit Walker

    Messages:
    496
    Likes Received:
    16
    Best Answers:
    0
    Trophy Points:
    0
    #3
    *Try not to get all the records. Only select those records you need for the task.
    * Your WHERE condition should have the condition which gives the "tightest filter"
    and you should have that column as an index.
     
    sadcox66, Jun 3, 2006 IP
  4. kLdd15

    kLdd15 Peon

    Messages:
    16
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #4
    Yeah, one of the most important things is the indexes for large tables.
     
    kLdd15, Jun 6, 2006 IP
  5. sacx13

    sacx13 Active Member

    Messages:
    438
    Likes Received:
    10
    Best Answers:
    0
    Trophy Points:
    58
    #5
    And if you expect just one result from your subquerys then use limit 1.

    Regards
     
    sacx13, Jun 7, 2006 IP