使用临时表中的大量数据填充表 - MySQL

时间:2011-01-05 14:19:26

标签: python sql mysql insert temp-tables

好的我有一个包含135,000行的临时MySQL表,从这个临时表中我想填充其他几个表。

首先,这是临时表的结构

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 个答案:

答案 0 :(得分:1)

这个怎么样:

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

答案 1 :(得分:1)

你正在为每一行做一个(可能很大的)子选择。

我建议对PROGRAM进行LEFT JOIN,然后只插入连接结果为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

顺便说一句:您是否考虑过(a)将您的代码打印得更具可读性,以及(b)不使用全部大写字段名称?

答案 2 :(得分:0)

我首先会看一下insert中嵌入式select语句的性能,尤其是NOT EXISTS子句。确保那里有好的索引。

另一个想法是将其分解为更小的块,这样就不会出现回滚空间问题。因此,看看你是否一次只能插入1000或10,000行,然后提交,然后再次运行。等

答案 3 :(得分:0)

将insert语句包装在事务中。

start transaction;

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

commit;

如果它仍然很慢,那么发布插入语句的选择部分的解释计划,以便我们可以看到发生了什么:P

答案 4 :(得分:0)

P.PROGTITLET.PROGTITLE创建索引。

答案 5 :(得分:0)

这是使用左/内连接和distinct关键字的组合。