2011-04-12 25 views
3

我有兩個表,其中第一個是我有14百萬,第二個是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的 對不起傢伙,我忘了提,有不同的數據庫:

的不規範化是調用紀律b和我正常化的調用imdb。

此致敬禮, 瓦爾特恩裏克。

+4

你正在處理什麼數據庫?你可以發佈有問題的表的DDL嗎? – Chandu 2011-04-12 18:09:46

+3

執行此操作的最有效方法是使用您所使用的SQL引擎本機的一些批量插入功能。 – 2011-04-12 18:13:00

+0

是的,有些數據庫允許您從查詢結果中填充表格。你正在使用哪個數據庫? – sjr 2011-04-12 18:13:19

回答

2

如果兩個表都在同一個數據庫中,那麼最有效的傳輸是在數據庫中完成所有操作,最好是通過發送一條SQL語句在那裏執行。

任何數據從d/b服務器移動到其他地方然後返回到d/b服務器的任何移動都應避免,除非有理由使其只能在服務器之外轉換。如果目的地是不同的服務器,那麼這是一個問題。

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主要有兩個思路,加快起來:

  1. 使用遊標來一個大表遍歷
  2. 使用準備好的語句來快速執行預先知道的命令

PS 。對於我的情況,這會使事情從年齡上升到秒,儘管在你的情況下,它仍然需要相當長的時間。所以最好從命令行執行,而不是一些Web界面(例如PhpMyAdmin)。

+0

注意 - 上面的查詢過於簡化,並沒有顯示PROCEDURES的全部功能,但您明白了並且可以添加您自己的任務。 – Laas 2011-04-12 18:35:40

+0

走的路;龐大的數據大小+複雜的邏輯要求數據庫服務器執行。 – 2011-04-12 19:18:28

+0

感謝您的幫助夥計,但我有兩個不同的數據庫,我該怎麼做你在這種情況下說的? – 2011-04-12 19:53:29

1

我剛剛爲〜150 Gb的數據做了這個。我爲每個表使用了一對合並語句。第一個合併語句表示「如果它不在目標表中,則將其複製到那裏」,第二個合併語句表示「如果它在目標表中,則將其從源刪除」。我把它們放在一個while循環中,並且每次操作只做10000行。保持在服務器上(而不是通過客戶端傳輸)對於性能來說將是一個巨大的利益。試一試!

相關問題