2010-06-04 50 views
9

Tôi muốn chuyển một số dữ liệu từ bảng này sang bảng khác (với lược đồ có thể khác). Giải pháp đơn giản mà bạn nghĩ đến là -di chuyển dữ liệu từ bảng này sang bảng khác, phiên bản postgresql

start a transaction with serializable isolation level; 
INSERT INTO dest_table SELECT data FROM orig_table,other-tables WHERE <condition>; 
DELETE FROM orig_table USING other-tables WHERE <condition>; 
COMMIT; 

Bây giờ nếu số lượng dữ liệu khá lớn và <condition> đắt tiền để tính toán? Trong PostgreSQL, một quy tắc RULE hoặc được lưu trữ có thể được sử dụng để xóa dữ liệu khi đang bay, chỉ đánh giá tình trạng một lần. Giải pháp nào tốt hơn? Có các lựa chọn khác không?

Trả lời

0

Bạn có thể đổ dữ liệu bảng vào một tệp, sau đó chèn nó vào một bảng khác bằng cách sử dụng COPY Thông thường COPY nhanh hơn INSERT.

+1

Tôi đã thực hiện một số chế biến thử nghiệm lượng lớn dữ liệu sử dụng trình kích hoạt, từng hàng và sử dụng quy trình được lưu trữ với một giao dịch duy nhất. Cách tiếp cận thủ tục được lưu trữ nhanh hơn. – pcent

+0

Bạn cũng nên tinh chỉnh máy chủ PostgreSQL của mình để nâng cao hiệu suất. Đọc: http://wiki.postgresql.org/wiki/Performance_Optimization – pcent

+0

yah, tôi nghĩ rằng hướng dẫn phải đủ điều kiện để nói rằng một COPY nhanh hơn một tập hợp các câu lệnh INSERT, mỗi câu một hàng. CH INSN ... CHỌN để sao chép dữ liệu xung quanh tôi nghĩ là tối ưu vì dữ liệu không được truyền qua bên ngoài trình thực thi. – araqnid

7

Nếu điều kiện quá phức tạp đến mức bạn không muốn thực thi hai lần (BTW có vẻ không phù hợp với tôi), một khả năng sẽ là ALTER TABLE ... ADD COLUMN trên bảng gốc để thêm trường boolean và chạy an UPDATE trên bảng để đặt trường đó thành true WHERE <condition>. Sau đó, các lệnh INSERTDELETE của bạn có thể chỉ cần kiểm tra cột này cho các mệnh đề WHERE của chúng.

Đừng quên xóa cột khỏi cả bảng nguồn và bảng đích sau đó!

Hmm, thậm chí ít xâm nhập hơn là tạo một bảng tạm thời mới với mục đích duy nhất là chứa các bản ghi PK mà bạn muốn đưa vào. Đầu tiên INSERT vào bảng này để "xác định" tập hợp các hàng để hoạt động, và sau đó tham gia với bảng này để sao chép bảng INSERTDELETE. Các kết nối này sẽ nhanh chóng vì các bảng PK được lập chỉ mục.


[EDIT] đề nghị Scott Bailey trong các ý kiến ​​rõ ràng là đúng cách để làm điều này, ước gì tôi đã nghĩ về nó bản thân mình! Giả sử tất cả các trường PK của bảng ban đầu sẽ có mặt trong bảng đích, không cần bảng tạm thời - chỉ cần sử dụng điều kiện phức hợp WHERE để chèn vào đích, sau đó DELETE từ bảng gốc bằng cách tham gia bảng này. Tôi cảm thấy ngu ngốc vì đã đề nghị một cái bàn riêng ngay bây giờ! :)

+0

Bảng tạm thời nhận được phiếu bầu của tôi. Cập nhật các hàng và sau đó xóa chúng có nghĩa là tạo ra rất nhiều rác trong heap, cũng như yêu cầu chạm vào lược đồ bảng (không phải điều đó thực sự quan trọng) – araqnid

+0

+1 cho bảng tạm thời cho PK. – rfusca

+4

Bạn sẽ không cần bảng tạm thời hoặc để làm một calc đắt tiền hai lần. Làm phép tính một lần khi bạn chèn vào bảng mới. Sau đó thực hiện xóa từ bảng cũ trong đó bản ghi nằm trong bảng mới. –

24

[Mở rộng trên dvv's answer]

Bạn có thể di chuyển đến một hiện bảng như sau. Đối với lược đồ chưa khớp, bạn nên chỉ định các cột.

WITH moved_rows AS (
    DELETE FROM <original_table> a 
    USING <other_table> b 
    WHERE <condition> 
    RETURNING a.* -- or specify columns 
) 
INSERT INTO <existing_table> --specify columns if necessary 
SELECT [DISTINCT] * FROM moved_rows; 

Nhưng bạn muốn di chuyển dữ liệu vào một mới bảng (không hiện có), cú pháp bên ngoài là khác nhau:

CREATE TABLE <new_table> AS 
WITH moved_rows AS (
    DELETE FROM <original_table> a 
    USING <other_table> b 
    WHERE <condition> 
    RETURNING a.* -- or specify columns 
) 
SELECT [DISTINCT] * FROM moved_rows; 
Các vấn đề liên quan