Làm cách nào để sao chép hiệu quả hàng triệu hàng từ bảng này sang bảng khác trong Postgresql?


36

Tôi có hai bảng cơ sở dữ liệu. Một chứa hàng trăm triệu hồ sơ. Hãy gọi nó là một history. Một cái khác được tính trên cơ sở hàng ngày và tôi muốn sao chép tất cả các hồ sơ của nó vào historymột.

Những gì tôi đã làm là chạy:

INSERT INTO history SELECT * FROM daily

Và nó đã thực hiện được mánh khóe trong một thời gian, nhưng nó bắt đầu ngày càng chậm hơn khi số lượng hồ sơ tiếp tục tăng lên. Bây giờ tôi có khoảng 2 triệu bản mà cần phải được sao chép từ dailyđể historyđi vào hoạt động duy nhất và phải mất quá nhiều thời gian để hoàn tất.

Có cách nào khác, hiệu quả hơn để sao chép dữ liệu từ bảng này sang bảng khác không?

Câu trả lời:


10

Nếu bạn có kế hoạch lưu giữ lịch sử trong thời gian dài (nhiều tháng), tôi khuyên bạn nên xem xét các tùy chọn phân vùng - có thể là một phân vùng cho mỗi ngày hoặc tuần, v.v. Nó cũng phụ thuộc vào các mẫu truy cập của bảng lịch sử của bạn (bạn có chạy các truy vấn truy cập dữ liệu qua các ngày không? Bạn có thực hiện nhiều kết hợp không, v.v.). Có một cái nhìn vào các khung nhìn cụ thể để lưu trữ tổng hợp / tóm tắt. http://www.postgresql.org/docs/9.3/static/ddl-partitioning.html http://www.postgresql.org/docs/9.3/static/sql-createm vật liệuview.html


Cảm ơn câu trả lời. Có vẻ như cách duy nhất để đi. Tôi cần phân vùng dữ liệu theo tháng và do đó thực hiện reindexing (vì việc tái tạo chỉ mục là một vấn đề ở đây) nhanh hơn nhiều.
Milovan Zogovic

16

Kết xuất bảng ở định dạng csv

COPY table TO '/tmp/table.csv' DELIMITER ',';

sử dụng lệnh COPY hiệu quả hơn nhiều đối với lượng lớn dữ liệu.

COPY table FROM '/tmp/table.csv' DELIMITER ',';

Kiểm tra tài liệu postgres tại http://www.postgresql.org/docs/civerse/static/sql-copy.html để biết thêm thông tin


1
Nó vẫn chạy rất, rất chậm ... Có lẽ nó phải làm gì đó với việc phải xây dựng lại một chỉ số khổng lồ như vậy? Có 160 triệu hàng trong historybảng và chúng tôi đang nối thêm 3 triệu hàng.
Milovan Zogovic

2
Trong số các bạn đang điền vào một bảng trống hoặc thêm nhiều hàng hơn số tồn tại, việc loại bỏ các chỉ mục không được phân cụm và tạo lại chúng một cách hiệu quả khi việc chuyển hoàn thành (trừ khi có sử dụng tích cực của bảng )
David Spillett

BTW, đây có phải là một hoạt động tắt hoặc nó là một cái gì đó bạn phải làm thường xuyên? Nếu trên cơ sở thường xuyên, tôi chắc chắn rằng bạn tạo ra một trình kích hoạt để bạn không phải trải qua thử thách này mỗi lần.
Fabrizio Mazzoni

@FabrizioMazzoni - Nó phải được thực hiện hàng ngày vào thời gian cụ thể (chụp ảnh nhanh đúng lúc).
Milovan Zogovic

@DavidSpillett - thực sự! Việc bỏ chỉ mục làm cho việc nhập rất nhanh (xem câu trả lời của tôi ở trên), tuy nhiên, việc tạo lại chỉ mục mất nhiều giờ (vì tôi có 160 triệu hàng trong cơ sở dữ liệu) ..
Milovan Zogovic

13

Vấn đề là với các chỉ số. Cáchistory bảng có 160M hàng được lập chỉ mục. Bằng cách chạy một trong hai COPY FROMhoặc INSERT INTO .. SELECTmất rất nhiều thời gian để không chèn các hàng, nhưng để cập nhật các chỉ mục. Khi tôi vô hiệu hóa các chỉ mục, nó đã nhập các hàng 3M trong 10 giây. Bây giờ tôi cần tìm cách nhanh hơn để reindexing bảng lớn.


3
Bạn thậm chí có cần chỉ mục trên một bảng lịch sử?
Sherlock

2
Thêm chỉ mục bằng từ khóa CONCURRENTLY
Akvel 16/2/2016

10

Bạn có thể dùng công cụ psql , tôi có thể hiệu quả, như sau,

psql -h ${DAILY_HOST_IP} -p ${PG_PORT} ${DB_NAME} ${USER_NAME} -c "copy daily to stdout " | psql -h ${HISTORY_HOST_IP} -p ${PG_PORT} ${DB_NAME} ${USER_NAME}  -c "copy history from stdin"

Ngoài ra, bạn có thể viết một kịch bản shell.


Giải pháp tuyệt vời mà không cần tập tin trung gian. Cũng rất nhanh, tôi đã sao chép một bảng 950 triệu hàng trong 1h20 (không có chỉ mục) giữa hệ thống tệp đĩa và mạng thông thường.
Le Droid

3

Tất nhiên đây không phải là một câu trả lời chính xác cho câu hỏi của bạn, nhưng nếu bạn không cần truy cập vào historybảng, bạn cũng có thể tạo ra một kết xuất SQL:

pg_dump -h host -p port -w -U user db > dump.sql

Sau đó, người ta có thể sử dụng một công cụ như gitđể tính toán sự khác biệt và lưu trữ điều này một cách hiệu quả.

git add dump.sql
git commit -m "temp dump"
git gc --aggressive

Điều này rất hữu ích vì hầu hết các phần trong cơ sở dữ liệu sẽ không thay đổi mỗi ngày. Thay vì lưu trữ toàn bộ một bản sao cho mỗi ngày, người ta có thể lưu trữ sự khác biệt giữa hai ngày.

Bạn có thể sử dụng một crontabcông việc sao cho bãi rác được xử lý mỗi ngày.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.