Заполнение таблицы большим количеством данных из временной таблицы - MySQL - PullRequest
1 голос
/ 05 января 2011

Хорошо, у меня есть временная таблица MySQL с 135 000 строк, из этой временной таблицы я хочу заполнить несколько других таблиц.

Прежде всего, это структура временной таблицы

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)

И это структура одной из таблиц, которые я планирую заполнить из этого.

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;

И вот как я делаю свою вставку втаблица программ

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 )

Однако, как это сделать, занимает очень много времени?

Спасибо, Пол

Хорошо, спасибо, ребята, у которых все еще есть несколько проблем с этим. Я пробую левый пример соединения, однако я обнаружил, что если таблица, в которую я вставляю, пуста для начала, тогда она вставляет дубликаты.Вот простой пример

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

. Он дважды вставляет жанр "новости" во временную таблицу.Теперь, если я запускаю эту команду 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;

, она вставляет «новости» дважды в таблицу жанров, что неверно.Если я снова выполню ту же команду, она не вставит новые строки.

Ответы [ 6 ]

1 голос
/ 05 января 2011

Вы делаете (возможно, большой) суб-выбор для каждой строки.

Я бы предложил сделать ЛЕВОЕ СОЕДИНЕНИЕ против ПРОГРАММЫ, а затем вставлять только те строки, в которых результат соединения равен NULL, следующим образом:

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

В качестве отступления: считали ли вы (а) красивую печать своего кода более читабельным и (б) не используете имена полей со всеми заглавными буквами?

1 голос
/ 05 января 2011

Как насчет этого:

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) 

Я считаю, что ваш NOT EXISTS должен выполняться для каждой выбранной строки. Замените его одним статическим подзапросом и отметьте NOT IN.

0 голосов
/ 06 января 2011

Это было сочетание использования левого / внутреннего соединения и отдельного ключевого слова.

0 голосов
/ 05 января 2011

Создать индекс для P.PROGTITLE и T.PROGTITLE.

0 голосов
/ 05 января 2011

оберните ваш оператор вставки в транзакцию.

start transaction;

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

commit;

если он все еще медленный, опубликуйте план объяснения выбранной части вашего оператора вставки, чтобы мы могли видеть, что происходит: P

0 голосов
/ 05 января 2011

Сначала я бы посмотрел на производительность встроенного оператора select в вашей вставке, особенно предложение NOT EXISTS.Убедитесь, что у вас там хорошие индексы.

Еще одна мысль - разбить его на более мелкие куски, чтобы у вас не было проблем с пространством отката.Посмотрите, можете ли вы вставить только 1000 или 10000 строк за раз, затем зафиксировать и снова запустить.и т.д.

...