Sao chép một bảng (bao gồm các chỉ mục) trong postgres


85

Tôi có một bảng postgres. Tôi cần xóa một số dữ liệu khỏi nó. Tôi sẽ tạo một bảng tạm thời, sao chép dữ liệu vào, tạo lại các chỉ mục và xóa các hàng tôi cần. Tôi không thể xóa dữ liệu khỏi bảng gốc vì bảng gốc này là nguồn dữ liệu. Trong một trường hợp, tôi cần nhận được một số kết quả phụ thuộc vào việc xóa X, trong một trường hợp khác, tôi sẽ cần xóa Y. Vì vậy, tôi cần tất cả dữ liệu gốc luôn ở xung quanh và có sẵn.

Tuy nhiên, có vẻ hơi ngớ ngẩn khi tạo lại bảng và sao chép lại nó và tạo lại các chỉ mục. Có cách nào trong postgres nói với nó "Tôi muốn có một bản sao hoàn chỉnh riêng biệt của bảng này, bao gồm cấu trúc, dữ liệu và chỉ mục" không?

Rất tiếc là PostgreSQL không có "TẠO BẢNG .. NHƯ X BAO GỒM CÁC CHỈ SỐ"

Câu trả lời:


108

PostgreSQL mới (kể từ 8.3 theo tài liệu) có thể sử dụng "BAO GỒM CHỈ SỐ":

# select version();
                                             version
-------------------------------------------------------------------------------------------------
 PostgreSQL 8.3.7 on x86_64-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3)
(1 row)

Như bạn có thể thấy, tôi đang thử nghiệm trên 8.3.

Bây giờ, hãy tạo bảng:

# create table x1 (id serial primary key, x text unique);
NOTICE:  CREATE TABLE will create implicit sequence "x1_id_seq" for serial column "x1.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "x1_pkey" for table "x1"
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "x1_x_key" for table "x1"
CREATE TABLE

Và xem nó trông như thế nào:

# \d x1
                         Table "public.x1"
 Column |  Type   |                    Modifiers
--------+---------+-------------------------------------------------
 id     | integer | not null default nextval('x1_id_seq'::regclass)
 x      | text    |
Indexes:
    "x1_pkey" PRIMARY KEY, btree (id)
    "x1_x_key" UNIQUE, btree (x)

Bây giờ chúng ta có thể sao chép cấu trúc:

# create table x2 ( like x1 INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES );
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "x2_pkey" for table "x2"
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "x2_x_key" for table "x2"
CREATE TABLE

Và kiểm tra cấu trúc:

# \d x2
                         Table "public.x2"
 Column |  Type   |                    Modifiers
--------+---------+-------------------------------------------------
 id     | integer | not null default nextval('x1_id_seq'::regclass)
 x      | text    |
Indexes:
    "x2_pkey" PRIMARY KEY, btree (id)
    "x2_x_key" UNIQUE, btree (x)

Nếu bạn đang sử dụng PostgreSQL trước 8.3, bạn có thể chỉ cần sử dụng pg_dump với tùy chọn "-t" để chỉ định 1 bảng, thay đổi tên bảng trong kết xuất và tải lại:

=> pg_dump -t x2 | sed 's/x2/x3/g' | psql
SET
SET
SET
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE

Và bây giờ bảng là:

# \d x3
                         Table "public.x3"
 Column |  Type   |                    Modifiers
--------+---------+-------------------------------------------------
 id     | integer | not null default nextval('x1_id_seq'::regclass)
 x      | text    |
Indexes:
    "x3_pkey" PRIMARY KEY, btree (id)
    "x3_x_key" UNIQUE, btree (x)

14
Bằng cách này, dãy khóa chính (x1_id_seq) sẽ được chia sẻ giữa hai bảng!
Jauzsika

2
Ops, với pg9.X, chuỗi khóa chính sẽ được chia sẻ khi sử dụng "INCLUDING CONSTRAINTS" (không phải "INCLUING INDEXES").
Peter Krauss

44
[CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name
    [ (column_name [, ...] ) ]
    [ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
    [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
    [ TABLESPACE tablespace ]
    AS query][1]  

Đây là một ví dụ

CREATE TABLE films_recent AS
  SELECT * FROM films WHERE date_prod >= '2002-01-01';

Một cách khác để tạo một bảng mới từ bảng đầu tiên là sử dụng

    CREATE TABLE films_recent (LIKE films INCLUDING INDEXES);  

    INSERT INTO films_recent
         SELECT *
           FROM books
          WHERE date_prod >= '2002-01-01';  

Lưu ý rằng Postgresql có một bản vá để khắc phục sự cố vùng bảng nếu phương pháp thứ hai được sử dụng


Không có "CHỈ SỐ BAO GỒM" trong postgres.
Rory

2
Bạn đang sử dụng phiên bản nào? Đọc doc mới nhất, nó là có
WolfmanDragon

6
với pg9.X, khi sử dụng "INCLUDING CONSTRAINTS" (không phải "INCLUING INDEXES"), chuỗi khóa chính sẽ được chia sẻ giữa hai bảng (!).
Peter Krauss

Có vẻ như nó có thể cần phải được CREATE TABLE my_table (LIKE...)thay vì CREATE TABLE my_table LIKE...để hoạt động. Câu trả lời đã được chỉnh sửa.
Jason Swett

@PeterKrauss bạn đã tìm ra thứ về trình tự khóa chính được chia sẻ chưa? Tôi đang cố SAO CHÉP một loạt dữ liệu vào một bảng mới. Tôi không thể bỏ bảng cũ và đổi tên bảng mới vì pk từ bảng mới trỏ vào bảng cũ.
yellottyellott 19/08

4

Tôi có một bảng postgres. Tôi cần xóa một số dữ liệu khỏi nó.

Tôi cho rằng ...

delete from yourtable
where <condition(s)>

... sẽ không hoạt động vì một số lý do. (Bạn muốn chia sẻ lý do đó chứ?)

Tôi sẽ tạo một bảng tạm thời, sao chép dữ liệu vào, tạo lại các chỉ mục và xóa các hàng tôi cần.

Nhìn vào pg_dump và pg_restore. Sử dụng pg_dump với một số tùy chọn thông minh và có thể chỉnh sửa đầu ra trước khi pg_restoring có thể thực hiện thủ thuật.


Vì bạn đang thực hiện phân tích kiểu "điều gì xảy ra nếu" trên dữ liệu, tôi tự hỏi liệu bạn có thể sử dụng chế độ xem tốt hơn không.

Bạn có thể xác định chế độ xem cho từng trường hợp bạn muốn kiểm tra dựa trên phủ định của những gì bạn muốn loại trừ. Tức là, xác định chế độ xem dựa trên những gì bạn muốn đưa vào. Ví dụ: nếu bạn muốn một "cửa sổ" trên dữ liệu mà bạn đã "xóa" các hàng có X = Y, thì bạn sẽ tạo dạng xem dưới dạng các hàng trong đó (X! = Y).

Chế độ xem được lưu trữ trong cơ sở dữ liệu (trong Danh mục hệ thống) dưới dạng truy vấn xác định của chúng. Mỗi khi bạn truy vấn dạng xem, máy chủ cơ sở dữ liệu sẽ tìm kiếm truy vấn cơ bản xác định nó và thực thi nó (ANDed với bất kỳ điều kiện nào khác mà bạn đã sử dụng). Có một số lợi ích đối với cách tiếp cận này:

  1. Bạn không bao giờ sao chép bất kỳ phần dữ liệu nào của mình.
  2. Các chỉ mục đã được sử dụng cho bảng cơ sở (bảng gốc, "thực" của bạn) sẽ được sử dụng (khi được trình tối ưu hóa truy vấn nhìn thấy là phù hợp) khi bạn truy vấn từng dạng xem / kịch bản. Không cần phải xác định lại hoặc sao chép chúng.
  3. Vì chế độ xem là "cửa sổ" (KHÔNG PHẢI là ảnh chụp) trên dữ liệu "thực" trong bảng cơ sở, bạn có thể thêm / cập nhật / xóa trên bảng cơ sở của mình và chỉ cần truy vấn lại các kịch bản chế độ xem mà không cần tạo lại bất kỳ thứ gì như dữ liệu thay đổi theo thời gian.

Tất nhiên, có một sự đánh đổi. Vì một dạng xem là một bảng ảo chứ không phải một bảng "thực" (cơ sở), bạn thực sự đang thực hiện một truy vấn (có lẽ phức tạp) mỗi khi bạn truy cập nó. Điều này có thể làm mọi thứ chậm lại một chút. Nhưng nó có thể không. Nó phụ thuộc vào nhiều vấn đề (kích thước và tính chất của dữ liệu, chất lượng của số liệu thống kê trong Danh mục hệ thống, tốc độ của phần cứng, tải sử dụng và nhiều hơn nữa). Bạn sẽ không biết cho đến khi bạn thử nó. Nếu (và chỉ khi) bạn thực sự thấy rằng hiệu suất chậm đến mức không thể chấp nhận được, thì bạn có thể xem xét các tùy chọn khác. (Chế độ xem vật thể hóa, bản sao của bảng, ... bất cứ thứ gì giao dịch không gian với thời gian.)


Tôi đã cập nhật câu hỏi để giải thích lý do tại sao tôi không thể xóa khỏi bảng gốc
Rory

4

Có rất nhiều câu trả lời trên web, một trong số chúng có thể được tìm thấy ở đây .

Tôi đã kết thúc việc làm như thế này:

create table NEW ( like ORIGINAL including all);
insert into NEW select * from ORIGINAL

Thao tác này sẽ sao chép lược đồ và dữ liệu bao gồm các chỉ mục, nhưng không bao gồm các trình kích hoạt và ràng buộc. Lưu ý rằng chỉ mục được chia sẻ với bảng gốc nên khi thêm hàng mới vào một trong hai bảng, bộ đếm sẽ tăng lên.


1

Tạo một bảng mới bằng cách sử dụng một lựa chọn để lấy dữ liệu bạn muốn. Sau đó đổi bàn cũ với bàn mới.

create table mynewone as select * from myoldone where ...
mess (re-create) with indexes after the table swap.

0

Một cách đơn giản là bao gồm tất cả:

CREATE TABLE new_table (LIKE original_table INCLUDING ALL);
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.