2012-06-25 23 views
15

複製是否有一個更efficent,複製所有記錄從一個表到另一個更省力的方式,這樣做:MySQL的高效的所有記錄從一個表到另一個

INSERT INTO product_backup SELECT * FROM product 

通常,product表將舉行大約50,000條記錄。兩張表的結構相同,並有31列。我想指出這是而不是我的數據庫設計,我已經繼承了一個遺留系統。

+5

我認爲這是最好的辦法。這樣你也可以保存索引。 –

+1

快速,這是一樣好,因爲它得到。當然,您可以推遲在備份表上創建索引,直到所有數據都被複制完畢,這將顯着提高插入速度。 – fvu

+0

這很有趣,謝謝。我對數據的複製很好奇,並想知道這是否是數據庫的漏洞('SELECT *'把我扔掉了,或者因爲查詢被構造的方式需要很長時間來處理)。如果這是一種可接受的複製數據的方式,那很好。 – crmpicco

回答

9

我認爲這是將記錄從一張表複製到另一張表的最佳方法。這樣你也保留了目標表的現有索引。

1

我不認爲這將是值得的50k表,但: 如果你有數據庫轉儲你可以從它重新加載表。當你想在一個又一個裝載表,你可以轉儲用sed命令更改表名稱: 這裏有一些提示: http://blog.tsheets.com/2008/tips-tricks/mysql-restoring-a-single-table-from-a-huge-mysqldump-file.html

的替代(取決於你的設計),將使用觸發器在原始表上插入,以便重複的表也獲取數據。

另一個更好的選擇是創建另一個MySQL實例,並以主從配置或日常轉儲主/從屬方式運行。

4
mysqldump -R --add-drop-table db_name table_name > filepath/file_name.sql 

這將採用指定表的轉儲,並使用drop選項在導入時刪除存在的表。然後呢,

mysql db_name < filepath/file_name.sql 
+0

我應該補充說我在做PHP代碼。這將在一系列INSERT和UPDATE在'product'表上執行之前完成,所以我會希望用PHP代碼而不是MySQL管理函數來完成。 – crmpicco

12

只有一樣東西你錯過了。特別是,如果你使用的是InnoDB,就是你要在你的SELECT語句中明確添加一個ORDER BY子句,以確保您的主鍵插入行(聚集索引)順序:

INSERT INTO product_backup SELECT * FROM product ORDER BY product_id 

考慮刪除二級指標在備份表上如果不需要的話。這也將節省服務器上的一些負擔。

最後,如果你正使用InnoDB,減少所需,只是明確地鎖定兩個錶行鎖的數量:

LOCK TABLES product_backup WRITE; 
LOCK TABLES product_id READ; 
INSERT INTO product_backup SELECT * FROM product ORDER BY product_id; 
UNLOCK TABLES; 

鎖定的東西可能不會產生巨大的變化,如行鎖定非常快(儘管速度不如桌子鎖),但是因爲你問了。

+0

我正在使用MyISAM引擎。我在前面的一篇文章中提到我繼承了遺留系統,所以現在是MyISAM。 – crmpicco

+0

無法排序創建一個不平衡的索引樹?在這種情況下,隨機順序對主鍵可能更好? –

+0

@DannyStaple,當使用MyISAM以排序順序插入索引時,樹是平坦的。這可以提高性能(不必重建索引),並節省空間。從[MySQL文檔](http://dev.mysql.com/doc/refman/5.0/en/myisam-storage-engine.html):「當按排序順序插入行時(如使用AUTO_INCREMENT列時),索引樹被拆分,以便高位節點只包含一個密鑰,這樣可以提高索引樹中的空間利用率。「 –

1

DROP目標表:

DROP TABLE DESTINATION_TABLE; 
CREATE TABLE DESTINATION_TABLE AS (SELECT * FROM SOURCE_TABLE); 
+0

如果OP要保存並添加到目標表中的數據已經存在,該怎麼辦? – Martin

+0

爲什麼刪除和創建表而不是DELETE FROM destination_table; INSERT INTO destination_table SELECT * FROM product?哪一個更有效? –

相關問題