2016-05-31 10 views
0

Ich habe eine Haupttabelle MainTable. hat ungefähr 4.5M Reihen. Dies wird es Abfrage erstellen:MySQL - Update mit Join dauert plötzlich für immer

create table MainTable(
    status_day date DEFAULT NULL, 
    i_station_id int DEFAULT NULL, 
    i_TZ int DEFAULT NULL, 
    CID int DEFAULT NULL, 
    Calc1 double DEFAULT NULL, 
    Calc2 double DEFAULT NULL, 
    ... 
    Calc80 double DEFAULT NULL, 
UNIQUE KEY uniqueindex (status_day, i_station_id, i_TZ, CID) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

Ich brauche mehrere feilds mit Werten aus anderen TEMP Tabelle zu aktualisieren. Es hat etwa 760K Zeilen, und es ist Aussage erstellen:

create temporary table TEMP (
    status_day date DEFAULT NULL, 
    i_station_id int DEFAULT NULL, 
    i_TZ int DEFAULT NULL, 
    CID int DEFAULT NULL,, 
    Calc13 double DEFAULT NULL, 
    Calc14 double DEFAULT NULL, 
    Calc17 double DEFAULT NULL, 
    Calc24 double DEFAULT NULL, 
    Calc68 double DEFAULT NULL, 
    Calc70 double DEFAULT NULL, 
UNIQUE KEY indexxx (status_day, i_station_id, i_TZ, CID) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

Aus irgendeinem Grund dieses Update-Abfrage:

nimmt ca. 3 Stunden. Ist das sinnvoll? scheint mir viel zu lang.

update MainTable as A join TEMP as B on 
     (A.status_day = B.status_day and 
     A.i_station_id = B.i_station_id and 
     A.i_TZ = B.i_TZ and 
     A.CID = B.CID) 
set 
    A.Calc13 = B.Calc13, 
    A.Calc14 = B.Calc14, 
    A.Calc17 = B.Calc17, 
    A.Calc24 = B.Calc24, 
    A.Calc68 = B.Calc68, 
    A.Calc70 = B.Calc70 

Dies ist das Ergebnis der

Explain select 
    * 
from MainTable as a join TEMP as b on 
    (a.status_day = b.status_day and 
    a.i_station_id = b.i_station_id and 
    a.i_TZ = b.i_TZ and 
    a.CID = b.CID) 




ID  select_type table type possible_keys key   key_len rows 
1  SIMPLE  b  ALL  indexxx        692967 
1  SIMPLE  a  ref  uniqueindex uniqueindex 23  1 

Irgendwelche Ideen?

Danke? :)

Update: Antwort: Eine Erhöhung von Speicher und CPU auf den Server löste dies sofort.

+0

Bessere Anzahl von Zeilen aus EXPLAIN Plan hinzufügen. Gibt es auch doppelte Werte unter den Feldern, denen Sie beitreten, wie leere Felder? Dadurch könnte Ihr Update eine sehr hohe Anzahl übereinstimmender Zeilen finden und die lange Ausführungszeit erklären. – iLikeMySql

+0

Hey :) keine Duplikate auf die verbundenen Felder sie sind ein eindeutiger Schlüssel auf beiden Tabellen ... Ich habe die Anzahl der Zeilen zum Explain-Ausgang hinzugefügt –

+0

Ich hatte einmal ein ähnliches Problem und es war die Disk I/O. Als rhavendc schrieb 3 Stunden sind viel zu viel für die Abfrage. Aber Ihre Abfrage scheint gut und die Anzahl der Zeilen ist wirklich nicht so hoch. Könnte es sein, dass zur gleichen Zeit eine weitere große Transaktion ausgeführt wurde? Ich würde die Abfrage nach Möglichkeit auf einem anderen Server testen, und wenn nicht, könnten Sie Kopien der Tabellen erstellen, Indizes neu erstellen und die Abfrage mit den Kopien testen, um sicherzustellen, dass sie nichts mit den Tabellen zu tun hat. – iLikeMySql

Antwort

0

Ich bin nicht sehr sicher, warum die Abfrage dauerte 3 Stunden, das ist absurd. Vielleicht gibt es etwas falsch mit den Spalten Sie verbinden, aber Sie können auch eine Abfrage wie folgt machen:

UPDATE MainTable A, TEMP B 
SET 
    Calc13 = B.Calc13, 
    Calc14 = B.Calc14, 
    Calc17 = B.Calc17, 
    Calc24 = B.Calc24, 
    Calc68 = B.Calc68, 
    Calc70 = B.Calc70 
WHERE 
    A.status_day = B.status_day 
    AND A.i_station_id = B.i_station_id 
    AND A.i_TZ = B.i_TZ 
    AND A.CID = B.CID 
0

Ein Teil der 3-Stunden-Kosten baut ein riesiges „Rollback“ log.

Ich würde ein Blick um 1000 Zeilen (oder weniger) pro Iteration erstellen. Oder, einfacher, aktualisieren Sie alle Zeilen für einen TEMP.status_day in einem einzigen UPDATE, dann weiter zum nächsten TEMP.status_day. Entweder eine gespeicherte Prozedur oder ein Anwendungscode könnte verwendet werden.

Wenn Sie das tun, achten Sie darauf, COMMIT nach jedem UPDATE. (Oder verwenden Sie einfach autocommit=1.)

More on chunking.