2012-06-25 32 views
15

Có hơn-efficent, cách ít mất thời gian sao chép tất cả các bản ghi từ một bảng khác mà làm điều này:MySQL hiệu quả sao chép tất cả các bản ghi từ một bảng khác

INSERT INTO product_backup SELECT * FROM product 

Thông thường, các bảng product sẽ tổ chức khoảng 50.000 hồ sơ. Cả hai bảng đều giống nhau về cấu trúc và có 31 cột trong đó. Tôi muốn chỉ ra đây là không thiết kế cơ sở dữ liệu của tôi, tôi đã thừa kế một hệ thống cũ.

+5

Tôi nghĩ đây là cách tốt nhất. Bằng cách này bạn cũng đang bảo tồn các chỉ mục. –

+1

Tốc độ nhanh đến mức tốt. Tất nhiên bạn có thể trì hoãn việc tạo chỉ mục trên bảng sao lưu cho đến sau khi tất cả dữ liệu đã được sao chép, điều đó sẽ làm tăng đáng kể tốc độ chèn. – fvu

+0

Thật thú vị, cảm ơn. Tôi đã tò mò xung quanh việc sao chép dữ liệu và tự hỏi liệu đây có phải là một cống trên cơ sở dữ liệu hay không (hoặc 'SELECT *' đã ném tôi ra, hoặc nếu phải mất một thời gian dài để xử lý vì cách truy vấn được xây dựng). Nếu đây là một cách có thể chấp nhận được để sao chép dữ liệu trên thì điều đó là tốt. – crmpicco

Trả lời

9

Tôi nghĩ đây là cách tốt nhất để sao chép các bản ghi từ một bảng sang bảng khác. Bằng cách này bạn cũng đang lưu giữ các chỉ mục hiện có của bảng mục tiêu.

1

Tôi không nghĩ rằng điều này sẽ xứng đáng với bảng 50k nhưng: Nếu bạn có kết xuất cơ sở dữ liệu, bạn có thể tải lại bảng từ đó. Như bạn muốn tải một bảng trong một khác, bạn có thể thay đổi tên bảng trong bãi với một lệnh sed: Ở đây bạn có một số gợi ý: http://blog.tsheets.com/2008/tips-tricks/mysql-restoring-a-single-table-from-a-huge-mysqldump-file.html

Một thay thế (tùy thuộc vào thiết kế của bạn) sẽ được sử dụng trigger trên bảng chèn ban đầu để bảng trùng lặp cũng nhận được dữ liệu.

Và một giải pháp thay thế tốt hơn là tạo một cá thể MySQL khác và chạy nó trong cấu hình master-slave hoặc trong thời gian đổ hàng loạt master/load slave.

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

Điều này sẽ mất một bảng được chỉ định có tùy chọn thả để xóa bảng hiện tại khi bạn nhập bảng. sau đó,

mysql db_name < filepath/file_name.sql 
+0

Tôi nên thêm rằng tôi đang làm điều này trong mã PHP. Nó sẽ được thực hiện trước khi một loạt các INSERT và UPDATE được thực hiện trên bảng 'product', vì vậy tôi sẽ tìm cách thực hiện nó trong mã PHP hơn là các hàm quản trị MySQL. – crmpicco

12

Chỉ có một thứ bạn đang bỏ lỡ. Đặc biệt, nếu bạn đang sử dụng InnoDB, là bạn muốn thêm một cách rõ ràng một mệnh đề ORDER BY trong câu lệnh SELECT của bạn để đảm bảo bạn đang chèn hàng trong khóa chính (clustered index) theo thứ tự:

INSERT INTO product_backup SELECT * FROM product ORDER BY product_id 

xem xét loại bỏ chỉ số thứ trên bảng sao lưu nếu chúng không cần thiết. Điều này cũng sẽ tiết kiệm một số tải trên máy chủ.

Cuối cùng, nếu bạn đang sử dụng InnoDB, giảm số lượng các ổ khóa hàng được yêu cầu và chỉ khóa một cách rõ ràng cả hai bảng:

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

Các công cụ khóa có thể sẽ không tạo sự khác biệt rất lớn, như khóa hàng là rất nhanh (mặc dù không nhanh như ổ khóa bảng), nhưng kể từ khi bạn hỏi.

+0

Tôi đang sử dụng công cụ MyISAM. Tôi đã đề cập trong một bài trước đó mà tôi đã thừa kế một hệ thống di sản, vì vậy nó là MyISAM cho thời điểm này. – crmpicco

+0

không thể đặt hàng tạo cây chỉ mục không cân bằng? Trong trường hợp nào, thứ tự ngẫu nhiên có thể tốt hơn cho khóa chính? –

+0

@DannyStaple, cây bằng phẳng khi chèn vào một chỉ mục theo thứ tự sắp xếp với MyISAM. Điều này cải thiện hiệu suất (không phải xây dựng lại chỉ mục), cũng như tiết kiệm không gian. Từ [tài liệu MySQL] (http://dev.mysql.com/doc/refman/5.0/en/myisam-storage-engine.html): "Khi hàng được chèn vào thứ tự sắp xếp (như khi bạn đang sử dụng cột AUTO_INCREMENT), cây chỉ mục được phân tách sao cho nút cao chỉ chứa một khóa. Điều này cải thiện việc sử dụng không gian trong cây chỉ mục. " –

1

DROP bảng điểm đến:

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

nếu có dữ liệu đã có trong bảng đích mà OP muốn giữ lại và thêm vào? – Martin

+0

lý do thả và tạo bảng thay vì DELETE FROM destination_table; INSERT INTO destination_table SELECT * TỪ sản phẩm? Cái nào hiệu quả hơn? –

Các vấn đề liên quan