2011-01-05 3 views
1

Ok Ich habe eine temporäre MySQL-Tabelle mit 135.000 Zeilen, aus dieser temporären Tabelle möchte ich mehrere andere Tabellen auffüllen.Füllen einer Tabelle mit einer großen Menge von Daten aus einer temporären Tabelle - MySQL

Zunächst einmal ist dies die Struktur der temporären Tabelle

CREATE TEMPORARY TABLE TVTEMPTABLE ( PROGTITLE TEXT, SUBTITLE TEXT, EPISODE TEXT, YR YEAR, DIRECTOR TEXT, PERFORMERS TEXT, PREMIERE BOOL, FILM BOOL, RPEAT BOOL, SUBTITLES BOOL, WIDESCREEN BOOL, NEWSERIES BOOL, DEAFSIGNED BOOL, BNW BOOL, STARRATING TINYINT, CERTIFICATE VARCHAR(5), GENRE VARCHAR(50), DESCRIPTION TEXT, CHOICE BOOL, PROGDATE DATE, STARTIME TIME, ENDTIME TIME, DURATION INT, CHANNELID INT NOT NULL)

Und das ist die Struktur von einem der Tische plane ich von diesen zu füllen.

CREATE TABLE PROGRAMME ( PROGRAMMEID INT NOT NULL AUTO_INCREMENT, GENREID INT NOT NULL, PROGTITLE VARCHAR(50), YR YEAR, DIRECTOR VARCHAR(50), PERFORMERS TEXT, FILM BOOL, WIDESCREEN BOOL, BNW BOOL, CERTIFICATE VARCHAR(5), DESCRIPTION TEXT, PRIMARY KEY(PROGRAMMEID), INDEX (GENREID), FOREIGN KEY (GENREID) REFERENCES GENRE(GENREID) ) ENGINE=INNODB;

Und das ist, wie ich meinen Einsatz an die Programmtabelle jedoch tue

INSERT INTO PROGRAMME ( GENREID, PROGTITLE, YR, DIRECTOR, PERFORMERS, FILM, WIDESCREEN, BNW, CERTIFICATE, DESCRIPTION) SELECT G.GENREID, T.PROGTITLE, T.YR, T.DIRECTOR, T.PERFORMERS, T.FILM, T.WIDESCREEN, T.BNW, T.CERTIFICATE, T.DESCRIPTION FROM TVTEMPTABLE T,GENRE G WHERE G.GENRENAME = T.GENRE AND NOT EXISTS ( SELECT * FROM PROGRAMME P WHERE P.PROGTITLE = T.PROGTITLE)

Dies ist eine sehr sehr lange Zeit zu tun, wie soll ich diesen Ansatz?

Danke, Paul

Ok Danke Jungs noch ein paar Probleme mit diesem, die ich die LEFT JOIN Beispiel bin versucht, ich habe jedoch festgestellt, dass, wenn die Tabelle in ich das Einfügen ist leer zu beginnen Allerdings fügt es dann Duplikate ein. Hier ein einfaches Beispiel:

CREATE TEMPORARY TABLE TEMP(
    GENRENAME TEXT); 

CREATE TABLE GENRE(
    GENREID INT NOT NULL AUTO_INCREMENT, 
    GENRENAME TEXT, PRIMARY KEY(GENREID) 
) ENGINE=INNODB; 

INSERT INTO TEMP(
    GENRENAME) 
VALUES("news"); 

INSERT INTO TEMP(
    GENRENAME) 
VALUES("news"); 

Damit wird das Genre "Nachrichten" zweimal in die temporäre Tabelle eingefügt. Jetzt, wenn ich diesen SQL-Befehl

INSERT INTO GENRE(
    GENRENAME) 
SELECT 
    T.GENRENAME 
FROM 
    TEMP T 
LEFT JOIN 
    GENRE G ON G.GENRENAME=T.GENRENAME 
WHERE 
    G.GENRENAME IS NULL; 

ausführen Es fügt "Nachrichten" zweimal in die Genrentabelle ein, die falsch ist. Wenn ich den gleichen Befehl erneut ausführe, fügt es korrekt keine neuen Zeilen ein.

Antwort

1

Wie wäre es damit:

INSERT INTO PROGRAMME (GENREID, PROGTITLE, YR, DIRECTOR, PERFORMERS, FILM, WIDESCREEN, BNW, CERTIFICATE, DESCRIPTION) 
SELECT G.GENREID, T.PROGTITLE, T.YR, T.DIRECTOR, T.PERFORMERS, T.FILM, T.WIDESCREEN, T.BNW, T.CERTIFICATE, T.DESCRIPTION 
FROM TVTEMPTABLE T,GENRE G 
WHERE G.GENRENAME = T.GENRE 
AND T.PROGTITLE NOT IN (SELECT DISTINCT P.PROGTITLE FROM PROGRAMME P) 

Ich glaube, Ihr NOT EXISTS für jede ausgewählte Zeile auszuführen hat. Ersetzen Sie es durch eine einzelne statische Unterabfrage und überprüfen Sie NOT IN darauf.

+0

Genau. Eine korrelierte Unterabfrage ist hier fehlerhaft. Du könntest (ich würde es sowieso) es auch in eine linke Verbindung umschreiben. – Mchl

+0

Ich habe es auch versucht, aber es scheint auch zu laufen für eine lange Zeit, erwarte ich zu viel? – PDStat

0

Ich würde zuerst die Leistung der eingebetteten Select-Anweisung in Ihrem Einfügen, insbesondere die NOT EXISTS-Klausel betrachten. Stellen Sie sicher, dass Sie dort gute Indizes haben.

ein anderer Gedanke ist, es in kleinere Stücke zu brechen, so dass Sie Rollbackraumprobleme nicht haben. Sehen Sie, ob Sie nur 1000 oder 10.000 Zeilen gleichzeitig einfügen können, dann commit und dann erneut.

usw.
0

verpacken Sie Ihre Insert-Anweisung in eine Transaktion.

start transaction; 

insert into programme (...) select ... from tvtemptable ... 

commit; 

wenn es immer noch langsam ist dann poste der Plan des Auswahl Teil Ihrer Insert-Anweisung erklären, damit wir sehen, was los ist: P

0

einen Index erstellen für P.PROGTITLE und T.PROGTITLE.

1

Sie machen eine (möglicherweise große) Unterauswahl für jede Zeile.

Ich möchte einen LEFT JOIN gegen PROGRAM empfehlen tun, und dann Reihen nur Einfügen, wo das Ergebnis NULL beitreten, wie folgt:

INSERT INTO PROGRAMME (
    GENREID, PROGTITLE, YR, DIRECTOR, 
    PERFORMERS, FILM, WIDESCREEN, BNW, 
    CERTIFICATE, DESCRIPTION) 
SELECT 
    G.GENREID, T.PROGTITLE, T.YR, T.DIRECTOR, 
    T.PERFORMERS, T.FILM, T.WIDESCREEN, T.BNW, 
    T.CERTIFICATE, T.DESCRIPTION 
FROM 
    TVTEMPTABLE T 
    INNER JOIN GENRE G ON G.GENRENAME=T.GENRE 
    LEFT JOIN PROGRAMME P ON P.PROGTITLE=T.PROGTITLE 
WHERE 
    P.PROGTITLE IS NULL 

Als beiseite: Haben Sie darüber nachgedacht, (a) recht-Druck Ihrer Code besser lesbar sein und (b) keine Großbuchstaben-Feldnamen verwenden?

+0

Danke, ich versuche ein paar dieser Vorschläge aus, Datenbanken/SQL-Zeug ist alles ziemlich neu für mich. Interessant, welche Zeit sollte ich erwarten? Ich habe Ihr Beitrittsbeispiel verwendet und es läuft immer noch nach fünf Minuten. – PDStat

0

Dies war eine Kombination aus linker/innerer Verknüpfung und dem eindeutigen Schlüsselwort.