2016-07-29 17 views
0

dies meine einfache innere Join:MYSQL INNER mit Index ist langsam 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 

Tisch "ASSNZ" hat 213.886 Zeilen mit dem Index "idUtente", "idServizio"

Tisch "ACQ" hat 8950 Zeilen mit dem Index "idContatto", "idServizio"

ASSNZ Tabelle:

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 Tabelle:

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; 

ist dies mein ERKLÄREN der select

enter image description here

Jetzt, da die Abfrage langsam, während 1,5 s/2,0 s ??

Etwas falsch?

UPDATE

haben neuen Index (mit der Antwort des John Bollinger) auf den Tisch 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; 

neuen Index zu der Tabelle ciac_serviziAcquistati_ITA hinzugefügt:

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

New ERKLäRT :

enter image description here

Aber es ist immer langsam :(

+0

Ich hatte einmal dieses Problem, wo die Spaltendefinitionen unterschiedlich waren. Die Spalten, die Sie verbinden, sind "INT NOT NULL" in einer Tabelle und "INT DEFAULT NULL" in einer anderen Tabelle. Können Sie die Spaltendefinitionen gleich machen? (Natürlich, tun Sie es auf einer Testtabelle und/oder db, nicht auf Live-Daten, falls etwas schief geht) – charmeleon

+0

@charmeleon jetzt die Spalten Definition sind die gleichen (INT NOT NULL). Aber die Abfrage ist immer langsam – marcozipsp

+0

Wie groß ist die Tabelle 'ciac_corsi_assenze' vs' ciac_serviziacquistati_ita'? Es sieht so aus, als ob Ihre Abfrage im Prinzip jede Zeile von 'ciac_corsi_assenze' auswählt (da es keine 'WHERE'-Bedingung gibt). Wenn 'ciac_serviziacquistati_ita' eine signifikant kleinere Tabelle ist, möchten Sie vielleicht zuerst die Abfrage aus der kleineren Tabelle" fahren ". – maresa

Antwort

0

Ihre Tabellen separate Indizes für verschiedene Spalten von Interesse haben, aber MySQL höchstens einen Index der Tabelle verwendet, wird Ihre Anfrage auszuführen. Diese spezielle Abfrage würde wahrscheinlich durch die Tabelle ciac_corsi_assenze beschleunigt werden, die einen Index auf (idUtente, idServizio) hat (und ein solcher Index würde den existierenden nur auf (idUtente) ersetzen). Dies sollte MySQL erlauben, die Sortierung der Ergebniszeilen zu vermeiden, um die Gruppierung durchzuführen, und es wird mehr bei der Ausführung der Verknüpfung helfen, als dies bei den vorhandenen Indizes der Fall ist.

Die Abfrage würde wahrscheinlich weiter durch Tabelle ciac_serviziAcquistati_ITA mit einem Index auf (idContatto, idServizio) oder sogar auf (idContatto, idServizio, ritirato) beschleunigt werden. Beides würde den bestehenden Index für nur (idContatto) ersetzen.

+0

Danke John, aber hat nicht funktioniert :(es ist immer langsam – marcozipsp

+0

@marcozipsp, Ihre Query ist nicht sehr komplex Wenn es (jetzt) ​​von den am besten geeigneten Indizes unterstützt wird, dann ist der einzige andere Bereich der Verbesserung, die Hardware zu verbessern, auf der MySql läuft. Schnellere Festplatte (und sicher sein, dass es * lokale * Festplatte), mehr Arbeitsspeicher und weniger Konflikte für die CPU können helfen, aber bevor Sie diese in Betracht ziehen, überprüfen Sie Ihren Abfrageplan, um zu überprüfen, ob die neuen Indizes verwendet werden .. –

+0

sehen Sie das neueste Update – marcozipsp

0

John ging die richtige Richtung. Die Reihenfolge der Spalten im zusammengesetzten Index muss jedoch geändert werden.

Für die GROUP BY, diese benötigt wird (auf ASSNZ):

INDEX(idServizio, idUtente) 

(und das sollte KEY(idServizio) ersetzen, aber nicht KEY(idUtente))

Dann ACQ Bedürfnisse, in dieser Reihenfolge:

INDEX(idContatto, idServizio, stato_allievo) 

ersetzen nur KEY(idContatto).