如何在MySQL中优化视图?

时间:2016-08-15 13:28:35

标签: mysql sql optimization explain

加载需要60秒,我该如何优化?

解释结构:

explain tablename;

IMG:http://i.stack.imgur.com/TfbY3.png

解释SQL

explain select * from tablename;

IMG:http://i.stack.imgur.com/jHI47.png

REAL DB

DROP TABLE IF EXISTS `afiliados`;
CREATE TABLE `afiliados` (
  `id_afiliado` int(10) NOT NULL AUTO_INCREMENT,
  `clave_panel` char(15) COLLATE latin1_spanish_ci DEFAULT NULL,
  `clave_panel_ask` datetime DEFAULT NULL,
  `id_trabajador` char(20) COLLATE latin1_spanish_ci DEFAULT NULL,
  `persona` char(1) COLLATE latin1_spanish_ci DEFAULT 'H',
  `Estado` int(10) NOT NULL DEFAULT '0',
  `doc_fiscal` int(10) DEFAULT NULL,
  `id_fiscal` char(20) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Nombre` char(25) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Apellidos` char(50) COLLATE latin1_spanish_ci DEFAULT NULL,
  `fecha_nacimiento` datetime DEFAULT NULL,
  `Telefono Principal` char(12) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Telefono Secundario` char(12) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Fecha_Alta` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `Fecha_Aprobacion` datetime DEFAULT NULL,
  `id_cuenta_aprobacion` int(11) DEFAULT NULL,
  `Fecha_Documentacion` datetime DEFAULT NULL,
  `Fecha_Alta_Sindicato` datetime DEFAULT NULL,
  `Fecha_Baja_Sindicato` datetime DEFAULT NULL,
  `Motivo_Baja_Sindicato` char(255) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Fecha_Desafiliacion` char(255) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Fax` char(12) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Direccion` char(100) COLLATE latin1_spanish_ci DEFAULT NULL,
  `CP` char(5) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Ciudad` char(35) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Provincia` char(25) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Pais` char(2) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Nacionalidad` char(2) COLLATE latin1_spanish_ci NOT NULL DEFAULT '',
  `Email` char(50) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Email_secundario` char(50) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Id_delegado` int(10) DEFAULT NULL,
  `Comentario` char(255) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Interno` char(255) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Eliminado` tinyint(1) NOT NULL DEFAULT '0',
  `Es_Delegado` tinyint(1) NOT NULL DEFAULT '0',
  `id_cuenta` int(10) DEFAULT NULL,
  `Fecha_mod` datetime DEFAULT NULL,
  `mod_id_cuenta` int(10) DEFAULT NULL,
  `noemail` tinyint(1) NOT NULL DEFAULT '0',
  `noemail_public` tinyint(1) NOT NULL DEFAULT '0',
  `noemail_fact` tinyint(1) NOT NULL DEFAULT '0',
  `noti_alta` datetime DEFAULT NULL,
  `noti_fact` datetime DEFAULT NULL,
  `noti_baja` datetime DEFAULT NULL,
  `fecha_star_facturacion` datetime DEFAULT NULL,
  `fecha_proxima_facturacion` datetime DEFAULT NULL,
  `ciclo_mensual_facturacion` int(10) unsigned NOT NULL DEFAULT '3',
  `fecha_sync` datetime DEFAULT NULL,
  `fecha_chk` datetime DEFAULT NULL,
  `LOPD` tinyint(1) NOT NULL DEFAULT '0',
  `ncarnet` int(10) DEFAULT NULL,
  `id_caja` int(10) unsigned NOT NULL DEFAULT '0',
  `caja_fecha_add` datetime DEFAULT NULL,
  `id_cuenta_caja_add` int(10) DEFAULT '0',
  `caja_fecha_del` datetime DEFAULT NULL,
  `id_cuenta_caja_del` int(10) DEFAULT '0',
  PRIMARY KEY (`id_afiliado`),
  KEY `apellidos` (`Apellidos`),
  KEY `Email` (`Email`),
  KEY `es_delegado` (`Es_Delegado`),
  KEY `id_caja` (`id_caja`),
  KEY `id_cuenta` (`id_cuenta`),
  KEY `id_delegado` (`Id_delegado`),
  KEY `id_fiscal` (`id_fiscal`),
  KEY `id_trabajador` (`id_trabajador`),
  KEY `nombre` (`Nombre`)
) ENGINE=MyISAM AUTO_INCREMENT=4467 DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci ROW_FORMAT=DYNAMIC;



INSERT INTO `afiliados` VALUES (194,NULL,NULL,'XXXXX','M',1,1,'XXXXX','Frank','Poland','1967-11-13 00:00:00','0000000','','2012-08-08 10:35:31','2012-08-08 21:05:59',0,'2012-08-09 00:00:00','2005-04-04 00:00:00',NULL,NULL,NULL,'','Adress','00000','Sevilla','Sevilla','es','es',NULL,NULL,NULL,NULL,NULL,0,0,NULL,NULL,NULL,0,0,0,NULL,NULL,NULL,NULL,NULL,3,NULL,NULL,0,NULL,0,NULL,NULL,NULL,NULL);




DROP TABLE IF EXISTS `contratos`;
CREATE TABLE `contratos` (
  `Id_contrato` int(10) NOT NULL AUTO_INCREMENT,
  `id_empresa` int(10) DEFAULT NULL,
  `Marca` char(255) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Departamento` char(255) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Localizacion` char(255) COLLATE latin1_spanish_ci DEFAULT NULL,
  `fecha_baja` datetime DEFAULT NULL,
  `id_cuenta_add` int(10) DEFAULT NULL,
  PRIMARY KEY (`Id_contrato`),
  KEY `id_empresa` (`id_empresa`)
) ENGINE=MyISAM AUTO_INCREMENT=1013 DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci ROW_FORMAT=FIXED;



INSERT INTO `contratos` VALUES (38,7,'Telefonica','CAOL','2º Planta',NULL,NULL),(193,11,'Vodafone','Atencion al Cliente','Planta Baja / 1ª Planta',NULL,3);


DROP TABLE IF EXISTS `empresa`;
CREATE TABLE `empresa` (
  `Id_empresa` int(10) NOT NULL AUTO_INCREMENT,
  `cif` char(10) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Razon_Social` char(60) COLLATE latin1_spanish_ci DEFAULT NULL,
  `empresa` char(40) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Centro` char(40) COLLATE latin1_spanish_ci DEFAULT NULL,
  `Provincia` char(30) COLLATE latin1_spanish_ci DEFAULT NULL,
  `localizacion_sindicato` char(100) COLLATE latin1_spanish_ci DEFAULT NULL,
  `id_setting` int(10) DEFAULT NULL,
  `direccion` char(100) COLLATE latin1_spanish_ci DEFAULT NULL,
  `cp` char(5) COLLATE latin1_spanish_ci DEFAULT NULL,
  `ciudad` char(30) COLLATE latin1_spanish_ci DEFAULT NULL,
  `id_cuenta_add` int(10) unsigned DEFAULT '0',
  `fecha_baja` datetime DEFAULT NULL,
  `id_cuenta_baja` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`Id_empresa`),
  KEY `cif` (`cif`),
  KEY `empresa` (`empresa`),
  KEY `id_setting` (`id_setting`)
) ENGINE=MyISAM AUTO_INCREMENT=871 DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci ROW_FORMAT=FIXED;



INSERT INTO `empresa` VALUES (7,'A78751997','ATENTO TELESERVICIOS, S.A.','Atento','Indotorre','Sevilla','2º Planta',13,NULL,NULL,NULL,0,NULL,NULL),(11,'B62916077','KONECTA BTO, S.L.','Konecta BTO','Prado de la Torre','Sevilla','1ª Planta (Pasillo Baño)',19,'Prado de la Torre s/n','41110','Bollulos',0,NULL,NULL);


DROP TABLE IF EXISTS `historico`;
CREATE TABLE `historico` (
  `Id_historico` int(10) NOT NULL AUTO_INCREMENT,
  `id_afiliado` int(10) DEFAULT NULL,
  `fecha_alta` datetime DEFAULT NULL,
  `tipo_contrato` smallint(5) DEFAULT NULL COMMENT 'Obra y Servicio ,etc ....',
  `fecha_baja` datetime DEFAULT NULL,
  `motivo_baja` smallint(5) DEFAULT NULL,
  `fecha_provision` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `id_contrato` int(10) DEFAULT NULL,
  `comentario` char(255) COLLATE latin1_spanish_ci DEFAULT NULL,
  `id_cuenta` int(10) DEFAULT NULL,
  `Fecha_mod` datetime DEFAULT NULL,
  `mod_id_cuenta` int(10) DEFAULT NULL,
  PRIMARY KEY (`Id_historico`),
  KEY `id_afiliado` (`id_afiliado`),
  KEY `id_contrato` (`id_contrato`),
  KEY `id_cuenta` (`id_cuenta`),
  KEY `tipo_contrato` (`tipo_contrato`)
) ENGINE=MyISAM AUTO_INCREMENT=4814 DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci ROW_FORMAT=FIXED;



INSERT INTO `historico` VALUES (227,194,'2005-04-04 00:00:00',0,'2014-01-01 00:00:00',-1,'2012-08-08 10:35:47',38,'',16,NULL,NULL),(1586,194,'2014-01-01 00:00:00',0,NULL,NULL,'2015-08-24 21:14:41',193,'',115,NULL,NULL);

观点:

DROP VIEW IF EXISTS `detalle_full_ko`;
CREATE VIEW `detalle_full_ko` AS 
select  `afiliados`.`id_afiliado` AS `Id_afiliado`,`afiliados`.`ncarnet` AS `ncarnet`,
        `afiliados`.`Id_delegado` AS `Id_delegado`,`afiliados`.`Fecha_Alta` AS `Fecha_Alta_Afiliado`,
        `afiliados`.`id_trabajador` AS `id_trabajador`,`afiliados`.`persona` AS `persona`,
        `afiliados`.`Nombre` AS `Nombre`,`afiliados`.`Apellidos` AS `Apellidos`,
        `afiliados`.`id_fiscal` AS `id_fiscal`,`afiliados`.`Email` AS `Email`,
        `afiliados`.`Email_secundario` AS `Email_secundario`,
        `afiliados`.`noemail` AS `noemail`,`afiliados`.`noemail_public` AS `noemail_public`,
        `afiliados`.`Telefono Principal` AS `Telefono Principal`,
        `afiliados`.`Telefono Secundario` AS `Telefono Secundario`,
        `afiliados`.`Fax` AS `Fax`,`afiliados`.`Ciudad` AS `Ciudad`,
        `afiliados`.`CP` AS `CP`,`afiliados`.`Provincia` AS `Provincia_Afiliado`,
        `afiliados`.`fecha_nacimiento` AS `fecha_nacimiento`,
        `afiliados`.`Estado` AS `Estado`,`afiliados`.`Es_Delegado` AS `Es_Delegado`,
        `afiliados`.`Eliminado` AS `Eliminado`,`detalle_historico_ko`.`fecha_alta` AS `Fecha_Alta_Empresa`,
        `empresa`.`Razon_Social` AS `Razon_Social`,`empresa`.`empresa` AS `nombre_empresa`,
        `empresa`.`Centro` AS `Centro`,`contratos`.`Departamento` AS `Departamento`,
        `contratos`.`Marca` AS `Marca`,`empresa`.`Provincia` AS `Provincia`,
        `empresa`.`localizacion_sindicato` AS `localizacion_sindicato`,
        `detalle_historico_ko`.`Id_contrato` AS `id_contrato`,
        `contratos`.`id_empresa` AS `id_empresa`,`detalle_historico_ko`.`tipo_contrato` AS `tipo_contrato`,
        `afiliados`.`Fecha_Alta_Sindicato` AS `Fecha_Alta_Sindicato`,
        `afiliados`.`Fecha_Baja_Sindicato` AS `Fecha_Baja_Sindicato`,
        `afiliados`.`fecha_sync` AS `fecha_sync`,`afiliados`.`noti_alta` AS `noti_alta`,
        `afiliados`.`noti_fact` AS `noti_fact`,`afiliados`.`noti_baja` AS `noti_baja`,
        `afiliados`.`Fecha_mod` AS `Fecha_mod`,`afiliados`.`LOPD` AS `LOPD`
    from  (((`contratos`
                            join  `empresa` on((`empresa`.`Id_empresa` = `contratos`.`id_empresa`)))
                    join  `detalle_historico_ko` on(((`empresa`.`Id_empresa` = `detalle_historico_ko`.`Id_empresa`)
                                      and  (`contratos`.`Id_contrato` = `detalle_historico_ko`.`Id_contrato`))))
            join  `afiliados` on((`detalle_historico_ko`.`id_afiliado` = `afiliados`.`id_afiliado`))
          )
    where  (`afiliados`.`LOPD` = 0)
    group by  `afiliados`.`id_afiliado`;


DROP VIEW IF EXISTS `detalle_full_ok`;
CREATE VIEW `detalle_full_ok` AS 
select  `afiliados`.`id_afiliado` AS `Id_afiliado`,`afiliados`.`ncarnet` AS `ncarnet`,
        `afiliados`.`Id_delegado` AS `Id_delegado`,`afiliados`.`Fecha_Alta` AS `Fecha_Alta_Afiliado`,
        `afiliados`.`id_trabajador` AS `id_trabajador`,`afiliados`.`persona` AS `persona`,
        `afiliados`.`Nombre` AS `Nombre`,`afiliados`.`Apellidos` AS `Apellidos`,
        `afiliados`.`id_fiscal` AS `id_fiscal`,`afiliados`.`Email` AS `Email`,
        `afiliados`.`Email_secundario` AS `Email_secundario`,
        `afiliados`.`noemail` AS `noemail`,`afiliados`.`noemail_public` AS `noemail_public`,
        `afiliados`.`Telefono Principal` AS `Telefono Principal`,
        `afiliados`.`Telefono Secundario` AS `Telefono Secundario`,
        `afiliados`.`Fax` AS `Fax`,`afiliados`.`Ciudad` AS `Ciudad`,
        `afiliados`.`CP` AS `CP`,`afiliados`.`Provincia` AS `Provincia_Afiliado`,
        `afiliados`.`fecha_nacimiento` AS `fecha_nacimiento`,
        `afiliados`.`Estado` AS `Estado`,`afiliados`.`Es_Delegado` AS `Es_Delegado`,
        `afiliados`.`Eliminado` AS `Eliminado`,`detalle_historico_ok`.`fecha_alta` AS `Fecha_Alta_Empresa`,
        `empresa`.`Razon_Social` AS `Razon_Social`,`empresa`.`empresa` AS `nombre_empresa`,
        `empresa`.`Centro` AS `Centro`,`contratos`.`Departamento` AS `Departamento`,
        `contratos`.`Marca` AS `Marca`,`empresa`.`Provincia` AS `Provincia`,
        `empresa`.`localizacion_sindicato` AS `localizacion_sindicato`,
        `detalle_historico_ok`.`Id_contrato` AS `id_contrato`,
        `contratos`.`id_empresa` AS `id_empresa`,`detalle_historico_ok`.`tipo_contrato` AS `tipo_contrato`,
        `afiliados`.`Fecha_Alta_Sindicato` AS `Fecha_Alta_Sindicato`,
        `afiliados`.`Fecha_Baja_Sindicato` AS `Fecha_Baja_Sindicato`,
        `afiliados`.`fecha_sync` AS `fecha_sync`,`afiliados`.`noti_alta` AS `noti_alta`,
        `afiliados`.`noti_fact` AS `noti_fact`,`afiliados`.`noti_baja` AS `noti_baja`,
        `afiliados`.`Fecha_mod` AS `Fecha_mod`,`afiliados`.`LOPD` AS `LOPD`
    from  (((`contratos`
                            join  `empresa` on((`empresa`.`Id_empresa` = `contratos`.`id_empresa`)))
                    join  `detalle_historico_ok` on(((`empresa`.`Id_empresa` = `detalle_historico_ok`.`Id_empresa`)
                                      and  (`contratos`.`Id_contrato` = `detalle_historico_ok`.`Id_contrato`))))
            join  `afiliados` on((`detalle_historico_ok`.`id_afiliado` = `afiliados`.`id_afiliado`))
          )
    where  (`afiliados`.`LOPD` = 0)
    group by  `afiliados`.`id_afiliado`;



DROP VIEW IF EXISTS `detalle_historico_ko`;
CREATE VIEW `detalle_historico_ko` AS 
select  high_priority `historico`.`Id_historico` AS `Id_historico`,
        `historico`.`id_afiliado` AS `id_afiliado`,`contratos`.`Id_contrato` AS `Id_contrato`,
        `historico`.`fecha_provision` AS `fecha_provision`,`empresa`.`Id_empresa` AS `Id_empresa`,
        `empresa`.`empresa` AS `Empresa`,`empresa`.`Provincia` AS `Provincia`,
        `empresa`.`Centro` AS `Centro`,`contratos`.`Marca` AS `Marca`,
        `contratos`.`Departamento` AS `Departamento`,`historico`.`fecha_alta` AS `fecha_alta`,
        `historico`.`fecha_baja` AS `fecha_baja`,`historico`.`comentario` AS `comentario`,
        `historico`.`tipo_contrato` AS `tipo_contrato`
    from  (`empresa`
            join  (`contratos`
                    join  `historico` on((`contratos`.`Id_contrato` = `historico`.`id_contrato`))) on((`empresa`.`Id_empresa` = `contratos`.`id_empresa`))
          )
    group by  `historico`.`id_afiliado`
    order by  isnull(`historico`.`fecha_baja`) desc,`historico`.`fecha_baja` desc;



DROP VIEW IF EXISTS `detalle_historico_ok`;
CREATE VIEW `detalle_historico_ok` AS 
select  high_priority `historico`.`Id_historico` AS `Id_historico`,
        `historico`.`id_afiliado` AS `id_afiliado`,`contratos`.`Id_contrato` AS `Id_contrato`,
        `historico`.`fecha_provision` AS `fecha_provision`,`empresa`.`Id_empresa` AS `Id_empresa`,
        `empresa`.`empresa` AS `Empresa`,`empresa`.`Provincia` AS `Provincia`,
        `empresa`.`Centro` AS `Centro`,`contratos`.`Marca` AS `Marca`,
        `contratos`.`Departamento` AS `Departamento`,`historico`.`fecha_alta` AS `fecha_alta`,
        `historico`.`fecha_baja` AS `fecha_baja`,`historico`.`comentario` AS `comentario`,
        `historico`.`tipo_contrato` AS `tipo_contrato`
    from  (`empresa`
            join  (`contratos`
                    join  `historico` on((`contratos`.`Id_contrato` = `historico`.`id_contrato`))) on((`empresa`.`Id_empresa` = `contratos`.`id_empresa`))
          )
    group by  `historico`.`Id_historico`,`historico`.`id_afiliado`
    order by  isnull(`historico`.`fecha_baja`) desc,`historico`.`fecha_baja` desc;

当选择视图detalle_full_ok 时,右转,但如果选择视图detalle_full_ko 出错。

查看视图detalle_full_ok 很慢,查看detalle_full_ko 很快。问题是查看detalle_full_ko 检索错误的 nombre_empresa 字段。

行: afiliados(4700) Empresa与(800) contratos(4700)

1 个答案:

答案 0 :(得分:0)

首先缩小查询以仅获取historicoId_historicohistoricoid_afiliado。也就是说,避免使用您在获取所需ID对时不需要的任何列和表:

SELECT DISTINCT Id_historico, id_afiliado
    FROM ...
    -- no GROUP BY or ORDER BY

然后使用它作为子查询来获取其余数据:

SELECT lots-of-stuff
    FROM ( the above select )
    JOIN back to all the tables
    WHERE ...
    GROUP BY -- probably needed again?
    ORDER BY ...

但是,GROUP BY并未包含SELECT中的所有非汇总值,因此它可能是“不正确的”#39}。并且可能会被ONLY_FULL_GROUP_BY标记为错误。