Sử dụng cột nối tiếp
Kế hoạch của bạn là thêm một chỉ mục khổng lồ không cần thiết cho 40 triệu (!) Hàng. Và bạn thậm chí không chắc nó sẽ là duy nhất. Tôi thực sự khuyên bạn nên chống lại con đường hành động đó. Thêm một serial
thay vào đó và được thực hiện với nó:
ALTER TABLE tbl ADD COLUMN tbl_id serial PRIMARY KEY;
Đó là tất cả những gì bạn cần làm. Phần còn lại diễn ra tự động. Thông tin thêm trong hướng dẫn sử dụng hoặc trong các câu trả lời có liên quan chặt chẽ sau:
Sự cố tự động tăng khóa chính PostgreSQL trong C ++
Hàm SQL tự động tăng dần
Thêm sê-ri
cột là hoạt động một lần, nhưng đắt tiền. Toàn bộ bảng phải được viết lại, chặn các cập nhật trong suốt thời gian hoạt động. Thực hiện tốt nhất mà không cần tải đồng thời vào giờ tắt. Tôi trích dẫn hướng dẫn ở đây
:
Vì điều này có hiệu quả ghi lại toàn bộ bảng, bạn cũng có thể tạo một bảng mới với một cột pk nối tiếp, chèn tất cả các hàng từ bảng cũ, để cho chuỗi này điền vào các giá trị mặc định từ trình tự của nó, bỏ cái cũ và đổi tên cái mới. Thông tin thêm về các câu trả lời có liên quan chặt chẽ sau:
Cập nhật hàng cơ sở dữ liệu mà không khóa bảng trong PostgreSQL 9.2
Thêm cột mới không có bảng khóa?
Đảm bảo rằng tất cả các câu lệnh INSERT của bạn có một danh sách đích, sau đó một cột bổ sung không thể làm chúng nhầm lẫn:
INSERT INTO tbl (col1, col2, ...) VALUES ...
Không phải:
INSERT INTO tbl VALUES ...
Một sê-ri
được triển khai bằng số nguyên
cột (4 byte).
Ràng buộc khóa chính được triển khai với chỉ mục duy nhất và NOT NULL
ràng buộc đối với các cột liên quan.
Nội dung của một chỉ mục được lưu trữ giống như các bảng. Bộ nhớ vật lý bổ sung là cần thiết riêng. Thông tin thêm về bộ nhớ thực trong câu trả lời có liên quan này:
Tính toán và tiết kiệm dung lượng trong PostgreSQL
Chỉ mục của bạn sẽ bao gồm 2 dấu thời gian (2 x 8 byte) cộng với một tên tệp dài bao gồm. đường dẫn (~ 50 byte?) Điều đó sẽ làm cho chỉ mục lớn hơn khoảng 2,5 GB (40M x 60 .. byte gì đó) và tất cả các hoạt động chậm hơn.
Xử lý các bản sao
Cách xử lý "nhập dữ liệu trùng lặp" tùy thuộc vào cách bạn nhập dữ liệu và "trùng lặp" được xác định chính xác như thế nào.
Nếu chúng ta đang nói về SAO CHÉP
, một cách sẽ là sử dụng bảng dàn tạm thời và thu gọn các bản sao bằng SELECT DISTINCT
đơn giản hoặc DISTINCT ON
trong INSERT
lệnh:
CREATE TEMP TABLE tbl_tmp AS
SELECT * FROM tbl LIMIT 0; -- copy structure without data and constraints
COPY tbl_tmp FROM '/path/to/file.csv';
INSERT INTO tbl (col1, col2, col3)
SELECT DISTINCT ON (col1, col2)
col1, col2, col3 FROM tbl_tmp;
Hoặc, cũng để cấm các bản sao với các hàng đã tồn tại:
INSERT INTO tbl (col1, col2, col3)
SELECT i.*
FROM (
SELECT DISTINCT ON (col1, col2)
col1, col2, col3
FROM tbl_tmp
) i
LEFT JOIN tbl t USING (col1, col2)
WHERE t.col1 IS NULL;
Nhiệt độ. bảng sẽ tự động bị xóa vào cuối phiên.
Nhưng cách khắc phục thích hợp sẽ là giải quyết gốc rễ của lỗi tạo ra các bản sao ngay từ đầu.
Câu hỏi ban đầu
1) Bạn hoàn toàn không thể thêm pk, nếu có một bản sao duy nhất trên tất cả các cột.
2) Tôi chỉ chạm vào cơ sở dữ liệu PostgreSQL phiên bản 8.1 với một cây sào dài năm feet. Nó quá cổ, lỗi thời và không hiệu quả, không được hỗ trợ nữa và có thể có một số lỗ hổng bảo mật chưa được khắc phục. Trang web lập phiên bản Postgres chính thức.
@David
đã cung cấp câu lệnh SQL.
3 &4) Vi phạm khóa trùng lặp. PostgreSQL gặp lỗi cũng có nghĩa là toàn bộ giao dịch được khôi phục. Nắm bắt điều đó trong một tập lệnh perl không thể thực hiện phần còn lại của giao dịch. Ví dụ, bạn sẽ phải tạo một tập lệnh phía máy chủ với plpgsql, nơi bạn có thể bắt các ngoại lệ.