2011-01-05 7 views
1

Ok J'ai une table MySQL temporaire avec 135 000 lignes, à partir de cette table temporaire, je veux remplir plusieurs autres tables.Remplir une table avec une grande quantité de données d'une table temporaire - MySQL

d'abord de tout cela est la structure de la table temporaire

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)

Et ceci est la structure de l'un des tableaux que je prévois pour remplir de cette situation.

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;

Et voilà comment je fais mon insertion à la table de programme

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)

Ceci est cependant prend un très très long temps de le faire, comment dois-je aborder ce sujet?

Merci, Paul

merci les gars Ok ayant encore quelques problèmes avec ce que je tente l'exemple se joindre à gauche, j'ai trouvé cependant que si la table j'insérer dans est vide pour commencer cependant, alors il insère des doublons. Voici un exemple simple

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"); 

Ceci insère le genre « nouvelles » dans la table temporaire à deux reprises. Maintenant, si je cours cette commande SQL

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

Il insère deux fois "nouvelles" dans la table de genre qui est faux. Si je réexécute la même commande, elle n'insère pas de nouvelles lignes correctement.

Répondre

1

Que diriez-vous ceci:

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) 

Je crois que votre NOT EXISTS doit exécuter pour chaque ligne sélectionnée. Remplacez-le par une seule sous-requête statique et cochez NOT IN dessus.

+0

Exactement. Une sous-requête corrélée est en cause ici. Vous pourriez (je le ferais de toute façon) également le réécrire à une jointure gauche. – Mchl

+0

J'ai aussi essayé avec ça, mais ça semble aussi fonctionner longtemps, est-ce que j'attends trop? – PDStat

0

Je voudrais d'abord examiner les performances de l'instruction select intégrée dans votre insert, en particulier la clause NOT EXISTS. Assurez-vous d'avoir de bons index là-bas. Une autre idée consiste à le diviser en blocs plus petits afin de ne pas avoir de problèmes d'espace de retour arrière. Donc, voyez si vous pouvez insérer seulement 1000 ou 10 000 lignes à la fois, puis validez, puis relancez. etc.

0

Enveloppez votre instruction d'insertion dans une transaction.

start transaction; 

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

commit; 

si elle est encore lent poster alors expliquer le plan de la partie de sélection de votre instruction d'insertion afin que nous puissions voir ce qui se passe: P

0

Créer un index pour P.PROGTITLE et T.PROGTITLE.

1

Vous effectuez un sous-sélection (éventuellement important) pour chaque ligne.

Je vous conseille de faire un LEFT JOIN contre le programme, et seulement insérer des lignes où la jointure est NULL, comme suit:

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 

En aparté: avez-vous pensé (a) jolie impression de votre code pour être plus lisible et (b) ne pas utiliser les noms de champs tout en majuscules?

+0

Merci à tous j'essaie quelques-unes de ces suggestions, les bases de données/sql est tout nouveau pour moi. Hors d'intérêt quel genre de temps devrais-je attendre? J'ai utilisé votre exemple de jointure et il fonctionne toujours après cinq minutes. – PDStat

0

Il s'agissait d'une combinaison de l'utilisation de la jointure gauche/interne et du mot clé distinct.

Questions connexes