2011-01-05 61 views
1

好吧我有一个临时的MySQL表,有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; 

它将“新闻”两次插入流派表中,这是错误的。如果我再次运行相同的命令,它正确不会插入任何新行。

回答

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

+0

准确。相关的子查询在这里是错误的。你可以(我会反正)也把它改写成左连接。 – Mchl 2011-01-05 14:37:28

+0

我也试过这个,但它似乎也跑了很长时间,我是否期待太多? – PDStat 2011-01-05 15:29:10

0

我会先看看嵌入式select语句在插入中的性能,特别是NOT EXISTS子句。确保你有很好的指标。

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

0

将您的插入语句包装在事务中。

start transaction; 

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

commit; 

,如果它仍然是缓慢的,然后张贴解释你的INSERT语句的选择部分的计划,所以我们可以看到这是怎么回事:P

0

创建P.PROGTITLET.PROGTITLE的索引。

1

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

我建议做一个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 

顺便说一句:你有没有考虑(一)漂亮,打印您的代码更具可读性并且(b)不使用全大写字段名称?

+0

感谢所有我正在尝试一些这些建议,数据库/ SQL的东西对我来说都是非常新的。出于兴趣,我应该期待什么样的时间?我已经使用了加入示例,并且在五分钟后仍然运行。 – PDStat 2011-01-05 15:17:57

0

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