Thay vì tạo một bảng mới, bạn cũng có thể chèn lại các hàng duy nhất vào cùng một bảng sau khi cắt bớt nó. Làm tất cả trong một lần giao dịch . Theo tùy chọn, bạn có thể tự động bỏ bảng tạm thời vào cuối giao dịch vớiON COMMIT DROP
. Xem bên dưới.
Cách tiếp cận này chỉ hữu ích khi có nhiều hàng cần xóa trên toàn bộ bảng. Đối với một vài bản sao, hãy sử dụngDELETE
.
Bạn đã đề cập đến hàng triệu hàng. Để làm cho hoạt động nhanh chóng, bạn muốn phân bổ đủ bộ đệm tạm thời cho phiên. Cài đặt phải được điều chỉnh trước khi bất kỳ bộ đệm tạm thời nào được sử dụng trong phiên hiện tại của bạn. Tìm hiểu kích thước bàn của bạn:
SELECT pg_size_pretty(pg_relation_size('tbl'));
Đặt cho temp_buffers
phù hợp. Làm tròn một cách hào phóng vì biểu diễn trong bộ nhớ cần nhiều RAM hơn một chút.
SET temp_buffers = 200MB; -- example value
BEGIN;
-- CREATE TEMPORARY TABLE t_tmp ON COMMIT DROP AS -- drop temp table at commit
CREATE TEMPORARY TABLE t_tmp AS -- retain temp table after commit
SELECT DISTINCT * FROM tbl; -- DISTINCT folds duplicates
TRUNCATE tbl;
INSERT INTO tbl
SELECT * FROM t_tmp;
-- ORDER BY id; -- optionally "cluster" data while being at it.
COMMIT;
Phương pháp này có thể vượt trội hơn so với việc tạo một bảng mới nếu tồn tại các đối tượng phụ thuộc. Chế độ xem, chỉ mục, khóa ngoại hoặc các đối tượng khác tham chiếu đến bảng. TRUNCATE
làm cho bạn bắt đầu với một slate sạch anyway (file mới trong nền) và nhiều nhanh hơn DELETE FROM tbl
với các bảng lớn (DELETE
trên thực tế có thể nhanh hơn với những chiếc bàn nhỏ).
Đối với các bảng lớn, nó thường nhanh hơn việc giảm chỉ mục và khóa ngoại, điền vào bảng và tạo lại các đối tượng . Liên quan đến các ràng buộc fk, bạn phải chắc chắn rằng dữ liệu mới là hợp lệ, nếu không bạn sẽ gặp phải trường hợp ngoại lệ khi cố gắng tạo fk.
Lưu ý rằng TRUNCATE
yêu cầu khóa tích cực hơnDELETE
. Đây có thể là vấn đề đối với các bảng có tải nặng, đồng thời.
Nếu TRUNCATE
không phải là một tùy chọn hoặc nói chung đối với các bảng vừa và nhỏ thì có một kỹ thuật tương tự với CTE sửa đổi dữ liệu (Postgres 9.1 +):
WITH del AS (DELETE FROM tbl RETURNING *)
INSERT INTO tbl
SELECT DISTINCT * FROM del;
-- ORDER BY id; -- optionally "cluster" data while being at it.
Chậm hơn đối với các bảng lớn, vì TRUNCATE
ở đó nhanh hơn. Nhưng có thể nhanh hơn (và đơn giản hơn!) Cho các bảng nhỏ.
Nếu bạn không có đối tượng phụ thuộc nào cả, bạn có thể tạo một bảng mới và xóa bảng cũ, nhưng bạn hầu như không thu được gì qua cách tiếp cận phổ quát này.
Đối với các bảng rất lớn không vừa với RAM khả dụng , việc tạo một bảng mới sẽ nhanh hơn đáng kể. Bạn sẽ phải cân nhắc điều này trước những rắc rối / chi phí có thể xảy ra với các đối tượng tùy thuộc.