我有两张桌子,第一张桌子里有1400万张,第二张桌子里有150万张数据。
所以我想知道如何将这些数据传输到另一个表进行规范化? 我如何将某种类型转换为另一种类型,例如:我有一个名为'year'的字段,但它的类型是varchar,但我想要它是一个整数,我该怎么做?
我想过在java中循环使用JDBC,但我认为这不是很有效。
// 1.5 million of data
CREATE TABLE dbo.directorsmovies
(
movieid INT NULL,
directorid INT NULL,
dname VARCHAR (500) NULL,
addition VARCHAR (1000) NULL
)
//14 million of data
CREATE TABLE dbo.movies
(
movieid VARCHAR (20) NULL,
title VARCHAR (400) NULL,
mvyear VARCHAR (100) NULL,
actorid VARCHAR (20) NULL,
actorname VARCHAR (250) NULL,
sex CHAR (1) NULL,
as_character VARCHAR (1500) NULL,
languages VARCHAR (1500) NULL,
genres VARCHAR (100) NULL
)
这是我的新表:
DROP TABLE actor
CREATE TABLE actor (
id INT PRIMARY KEY IDENTITY,
name VARCHAR(200) NOT NULL,
sex VARCHAR(1) NOT NULL
)
DROP TABLE actor_character
CREATE TABLE actor_character(
id INT PRIMARY KEY IDENTITY,
character VARCHAR(100)
)
DROP TABLE director
CREATE TABLE director(
id INT PRIMARY KEY IDENTITY,
name VARCHAR(200) NOT NULL,
addition VARCHAR(150)
)
DROP TABLE movie
CREATE TABLE movie(
id INT PRIMARY KEY IDENTITY,
title VARCHAR(200) NOT NULL,
year INT
)
DROP TABLE language
CREATE TABLE language(
id INT PRIMARY KEY IDENTITY,
language VARCHAR (100) NOT NULL
)
DROP TABLE genre
CREATE TABLE genre(
id INT PRIMARY KEY IDENTITY,
genre VARCHAR(100) NOT NULL
)
DROP TABLE director_movie
CREATE TABLE director_movie(
idDirector INT,
idMovie INT,
CONSTRAINT fk_director_movie_1 FOREIGN KEY (idDirector) REFERENCES director(id),
CONSTRAINT fk_director_movie_2 FOREIGN KEY (idMovie) REFERENCES movie(id),
CONSTRAINT pk_director_movie PRIMARY KEY(idDirector,idMovie)
)
DROP TABLE genre_movie
CREATE TABLE genre_movie(
idGenre INT,
idMovie INT,
CONSTRAINT fk_genre_movie_1 FOREIGN KEY (idMovie) REFERENCES movie(id),
CONSTRAINT fk_genre_movie_2 FOREIGN KEY (idGenre) REFERENCES genre(id),
CONSTRAINT pk_genre_movie PRIMARY KEY (idMovie, idGenre)
)
DROP TABLE language_movie
CREATE TABLE language_movie(
idLanguage INT,
idMovie INT,
CONSTRAINT fk_language_movie_1 FOREIGN KEY (idLanguage) REFERENCES language(id),
CONSTRAINT fk_language_movie_2 FOREIGN KEY (idMovie) REFERENCES movie(id),
CONSTRAINT pk_language_movie PRIMARY KEY (idLanguage, idMovie)
)
DROP TABLE movie_actor
CREATE TABLE movie_actor(
idMovie INT,
idActor INT,
CONSTRAINT fk_movie_actor_1 FOREIGN KEY (idMovie) REFERENCES movie(id),
CONSTRAINT fk_movie_actor_2 FOREIGN KEY (idActor) REFERENCES actor(id),
CONSTRAINT pk_movie_actor PRIMARY KEY (idMovie,idActor)
)
更新: 我正在使用SQL Server 2008。 对不起,我忘了提及不同的数据库:
未规范化的是调用纪律字符和我的规范化调用imdb。
祝你好运, Valter Henrique。
答案 0 :(得分:2)
如果两个表都在同一个数据库中,那么最有效的传输是在数据库中完成所有操作,最好是发送一个要在那里执行的SQL语句。
除非有理由只能在服务器外转换,否则应避免将数据从d / b服务器移动到其他地方然后再返回到d / b服务器。如果目的地是不同的服务器,那么这不是一个问题。
答案 1 :(得分:1)
虽然我的桌子与你的桌子相比相形见绌,但是我用存储过程解决了这个问题。对于MySQL,下面是我的脚本的简化(和未经测试)的本质,但类似的东西应该适用于所有主要的SQL基础。
首先,您应该添加一个新的整数年份列(示例中为int_year),然后使用以下过程迭代所有行:
DROP PROCEDURE IF EXISTS move_data;
CREATE PROCEDURE move_data()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE orig_id INT DEFAULT 0;
DECLARE orig_year VARCHAR DEFAULT "";
DECLARE cur1 CURSOR FOR SELECT id, year FROM table1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
PREPARE stmt FROM "UPDATE table1 SET int_year = ? WHERE id = ?";
read_loop: LOOP
FETCH cur1 INTO orig_id, orig_year;
IF done THEN
LEAVE read_loop;
END IF;
SET @year= orig_year;
SET @id = orig_id;
EXECUTE stmt USING @orig_year, @id;
END LOOP;
CLOSE cur1;
END;
要开始此过程,只需CALL move_data()
。
上面的SQL有两个主要的想法来加快它:
PS。对于我的情况,这会加速从几岁到几秒钟,但在你的情况下,它仍然需要相当长的时间。所以最好从命令行执行,而不是从某些Web界面(例如PhpMyAdmin)执行。
答案 2 :(得分:1)
我刚刚为~150 Gb的数据做了这个。我为每个表使用了一对合并语句。第一个合并语句说“如果它不在目标表中,则将其复制到那里”,第二个说“如果它在目标表中,则从源中删除”。我把两个都放在while循环中,每次只执行10000行。将它保留在服务器上(而不是通过客户端传输)将对性能产生巨大的好处。试一试!