MYSQL INNER JOIN索引速度慢

时间:2016-07-29 14:51:46

标签: mysql performance join indexing inner-join

这是我简单的内部联接:

    SELECT
        SUM(ASSNZ.assenzeDidattiche) AS TotaleAssenze,
        SUM(ASSNZ.ore) AS totale_parziale,
        FLOOR(((SUM(ASSNZ.assenzeDidattiche) / SUM(ASSNZ.ore)) * 100)) AS andamento,
        MAX(ASSNZ.dataLezione) AS ultima_lezione,
        ASSNZ.idServizio,
        ASSNZ.idUtente
    FROM
        ciac_corsi_assenze AS ASSNZ
    INNER JOIN
        ciac_serviziAcquistati_ITA AS ACQ
               ON ACQ.idContatto = ASSNZ.idUtente
              AND ACQ.idServizio = ASSNZ.idServizio
              AND ACQ.stato_allievo <> 'ritirato'
    GROUP BY
        ASSNZ.idServizio,
        ASSNZ.idUtente
表&#34; ASSNZ&#34;有213886行索引&#34; idUtente&#34;,&#34; idServizio&#34;

表&#34; ACQ&#34;有8950行索引&#34; idContatto&#34;,&#34; idServizio&#34;

ASSNZ表:

    CREATE TABLE `ciac_corsi_assenze` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `idUtente` int(11) DEFAULT NULL,
  `idServizio` int(11) DEFAULT NULL,
  `idCorso` int(11) DEFAULT NULL,
  `idCalendario` int(11) DEFAULT NULL,
  `modalita` varchar(255) DEFAULT NULL,
  `ore` int(11) DEFAULT NULL,
  `assenzeDidattiche` float DEFAULT NULL,
  `assenzeAmministrative` float DEFAULT NULL,
  `dataLezione` date DEFAULT NULL,
  `ora_inizio` varchar(8) DEFAULT NULL,
  `ora_fine` varchar(8) DEFAULT NULL,
  `dataFineStage` date DEFAULT NULL,
  `giustificata` varchar(128) DEFAULT NULL,
  `motivazione` longtext,
  `grouped` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idUtente` (`idUtente`) USING BTREE,
  KEY `idServizio` (`idServizio`) USING BTREE,
  KEY `dataLezione` (`dataLezione`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=574582 DEFAULT CHARSET=utf8;

ACQ表:

CREATE TABLE `ciac_serviziacquistati_ita` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `idServizio` int(11) NOT NULL,
  `idContatto` int(11) NOT NULL,
  `idAzienda` int(11) NOT NULL,
  `idSede` int(11) NOT NULL,
  `tipoPersona` int(11) NOT NULL,
  `num_registro` int(11) NOT NULL,
  `codice` varchar(255) CHARACTER SET latin1 DEFAULT NULL,
  `dal` date NOT NULL,
  `al` date NOT NULL,
  `ore` int(11) NOT NULL,
  `costoOrario` decimal(10,0) NOT NULL,
  `annoFormativo` varchar(128) CHARACTER SET latin1 NOT NULL,
  `stato_attuale` int(11) NOT NULL,
  `datore_attuale` int(11) NOT NULL,
  `stato_allievo` varchar(64) CHARACTER SET latin1 NOT NULL DEFAULT 'corsista',
  `data_ritiro` date DEFAULT NULL,
  `crediti_formativi` int(11) NOT NULL,
  `note` longtext CHARACTER SET latin1 NOT NULL,
  `valore_economico` decimal(10,2) NOT NULL,
  `dataInserimento` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idServizio` (`idServizio`) USING BTREE,
  KEY `idAzienda` (`idAzienda`) USING BTREE,
  KEY `idContatto` (`idContatto`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=9542 DEFAULT CHARSET=utf8;

这是我对选择

的解释

enter image description here

现在因为查询很慢,在1.5s / 2.0s ??

期间

有什么问题吗?

更新

将新索引(John Bollinger的回答)添加到表ciac_corsi_assenze:

PRIMARY KEY (`id`),
  KEY `dataLezione` (`dataLezione`) USING BTREE,
  KEY `test` (`idUtente`,`idServizio`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=574582 DEFAULT CHARSET=utf8;

在表ciac_serviziAcquistati_ITA中添加了新索引:

  PRIMARY KEY (`id`),
  KEY `idAzienda` (`idAzienda`) USING BTREE,
  KEY `test2` (`idContatto`,`idServizio`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=9542 DEFAULT CHARSET=utf8;

新解析:

enter image description here

但它总是很慢:(

2 个答案:

答案 0 :(得分:0)

您的表在各个感兴趣的列上都有单独的索引,但MySQL每个表最多使用一个索引来执行查询。这个特定的查询可能会被ciac_corsi_assenze索引(idUtente, idServizio)的表(idUtente)加速(这样的索引将取代仅ciac_serviziAcquistati_ITA上的现有索引)。这应该允许MySQL避免对结果行进行排序以执行分组,并且它将比任何现有索引更有助于执行连接。

查询可能会被表(idContatto, idServizio)的{​​{1}}或(idContatto, idServizio, ritirato)上的索引进一步加速。其中任何一个都将取代(idContatto)上的现有索引。

答案 1 :(得分:0)

约翰走向正确的方向。但是,复合索引中列的顺序需要更改。

对于GROUP BY,需要此订单(在ASSNZ上):

INDEX(idServizio, idUtente)

(这应该取代KEY(idServizio),而不是KEY(idUtente)

然后ACQ需要按此顺序:

INDEX(idContatto, idServizio, stato_allievo)

仅替换KEY(idContatto)