คัดลอกตาราง (รวมถึงดัชนี) ใน postgres


85

ฉันมีโต๊ะ postgres ฉันต้องการลบข้อมูลบางส่วนออก ฉันจะสร้างตารางชั่วคราวคัดลอกข้อมูลสร้างดัชนีใหม่และลบแถวที่ฉันต้องการ ฉันไม่สามารถลบข้อมูลจากตารางต้นฉบับได้เนื่องจากตารางต้นฉบับนี้เป็นแหล่งที่มาของข้อมูล ในกรณีหนึ่งฉันต้องการผลลัพธ์บางอย่างที่ขึ้นอยู่กับการลบ X ในอีกกรณีหนึ่งฉันจะต้องลบ Y ดังนั้นฉันต้องการให้ข้อมูลดั้งเดิมทั้งหมดอยู่รอบ ๆ และพร้อมใช้งานเสมอ

อย่างไรก็ตามดูเหมือนว่าจะโง่เล็กน้อยที่จะสร้างตารางขึ้นมาใหม่และคัดลอกอีกครั้งและสร้างดัชนีใหม่ มีอยู่แล้วใน postgres หรือไม่ที่จะบอกว่า "ฉันต้องการสำเนาของตารางนี้รวมถึงโครงสร้างข้อมูลและดัชนี"

น่าเสียดายที่ PostgreSQL ไม่มี "CREATE TABLE .. LIKE X INCLUDING INDEXES"

คำตอบ:


108

PostgreSQL ใหม่ (ตั้งแต่ 8.3 ตามเอกสาร) สามารถใช้ "INCLUDING INDEXES":

# 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)

อย่างที่คุณเห็นฉันกำลังทดสอบบน 8.3

ตอนนี้มาสร้างตาราง:

# 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

และดูว่ามีลักษณะอย่างไร:

# \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)

ตอนนี้เราสามารถคัดลอกโครงสร้าง:

# 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

และตรวจสอบโครงสร้าง:

# \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)

หากคุณใช้ PostgreSQL pre-8.3 คุณสามารถใช้ pg_dump พร้อมตัวเลือก "-t" เพื่อระบุ 1 ตารางเปลี่ยนชื่อตารางในดัมพ์และโหลดอีกครั้ง:

=> 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

และตอนนี้ตารางคือ:

# \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
ด้วยวิธีนี้ลำดับคีย์หลัก (x1_id_seq) จะถูกแชร์ระหว่างสองตาราง!
Jauzsika

2
Ops ด้วย pg9.X ลำดับคีย์หลักจะถูกแชร์เมื่อใช้ "INCLUDING CONSTRAINTS" (ไม่ใช่ "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]  

นี่คือตัวอย่าง

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

วิธีอื่นในการสร้างตารางใหม่ตั้งแต่แรกคือการใช้

    CREATE TABLE films_recent (LIKE films INCLUDING INDEXES);  

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

โปรดทราบว่า Postgresql มีโปรแกรมแก้ไขเพื่อแก้ไขปัญหาพื้นที่ตารางหากใช้วิธีที่สอง


ไม่มี "INCLUDING INDEXES" ใน postgres
รอรี

2
คุณใช้รุ่นอะไร? อ่านเอกสารล่าสุดอยู่ที่นั่น
WolfmanDragon

6
ด้วย pg9.X เมื่อใช้ "INCLUDING CONSTRAINTS" (ไม่ใช่ "INCLUING INDEXES") ลำดับคีย์หลักจะแชร์ระหว่างสองตาราง (!)
Peter Krauss

ดูเหมือนว่ามันอาจจะต้องCREATE TABLE my_table (LIKE...)แทนที่จะเป็นCREATE TABLE my_table LIKE...ในการทำงาน คำตอบที่แก้ไข
Jason Swett

@PeterKrauss คุณคิดออกลำดับคีย์หลักที่ใช้ร่วมกันหรือไม่? ฉันกำลังพยายามคัดลอกข้อมูลจำนวนมากลงในตารางใหม่ ฉันไม่สามารถวางตารางเก่าและเปลี่ยนชื่อใหม่ได้เพราะ pk จากตารางใหม่ชี้ที่ตารางเก่า
yellottyellott

5

มีคำตอบมากมายในเว็บนี้หนึ่งของพวกเขาสามารถพบได้ที่นี่

ฉันลงเอยด้วยการทำสิ่งนี้:

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

การดำเนินการนี้จะคัดลอกสคีมาและข้อมูลรวมทั้งดัชนี แต่ไม่รวมทริกเกอร์และข้อ จำกัด โปรดทราบว่าดัชนีจะแชร์กับตารางเดิมดังนั้นเมื่อเพิ่มแถวใหม่ในตารางใดตารางหนึ่งตัวนับจะเพิ่มขึ้น


4

ฉันมีโต๊ะ postgres ฉันต้องการลบข้อมูลบางส่วนออก

ฉันสันนิษฐานว่า ...

delete from yourtable
where <condition(s)>

... จะไม่ทำงานด้วยเหตุผลบางประการ (สนใจที่จะแบ่งปันเหตุผลนั้นหรือไม่?)

ฉันจะสร้างตารางชั่วคราวคัดลอกข้อมูลสร้างดัชนีใหม่และลบแถวที่ฉันต้องการ

ดูใน pg_dump และ pg_restore การใช้ pg_dump กับตัวเลือกที่ชาญฉลาดและอาจแก้ไขผลลัพธ์ก่อนที่ pg_restoring อาจทำเคล็ดลับ


เนื่องจากคุณกำลังทำการวิเคราะห์ข้อมูลประเภท "จะเกิดอะไรขึ้นถ้า" ฉันจึงสงสัยว่าคุณควรใช้มุมมองที่ดีกว่านี้หรือไม่

คุณสามารถกำหนดมุมมองสำหรับแต่ละสถานการณ์ที่คุณต้องการทดสอบโดยพิจารณาจากการปฏิเสธของสิ่งที่คุณต้องการยกเว้น กล่าวคือกำหนดมุมมองตามสิ่งที่คุณต้องการรวม เช่นหากคุณต้องการ "หน้าต่าง" บนข้อมูลที่คุณ "ลบ" แถวที่ X = Y คุณจะสร้างมุมมองเป็นแถวโดยที่ (X! = Y)

มุมมองถูกเก็บไว้ในฐานข้อมูล (ในแค็ตตาล็อกระบบ) เป็นการกำหนดคิวรี ทุกครั้งที่คุณสอบถามมุมมองเซิร์ฟเวอร์ฐานข้อมูลจะค้นหาแบบสอบถามพื้นฐานที่กำหนดและดำเนินการนั้น (AND กับเงื่อนไขอื่น ๆ ที่คุณใช้) แนวทางนี้มีประโยชน์หลายประการ:

  1. คุณไม่เคยทำซ้ำส่วนใดส่วนหนึ่งของข้อมูลของคุณ
  2. ดัชนีที่ใช้อยู่แล้วสำหรับตารางฐาน (ตาราง "จริง" เดิมของคุณ) จะถูกนำมาใช้ (ตามที่เห็นสมควรโดยเครื่องมือเพิ่มประสิทธิภาพการสืบค้น) เมื่อคุณสอบถามแต่ละมุมมอง / สถานการณ์ ไม่จำเป็นต้องกำหนดใหม่หรือคัดลอก
  3. เนื่องจากมุมมองเป็น "หน้าต่าง" (ไม่ใช่ shapshot) บนข้อมูล "จริง" ในตารางฐานคุณจึงสามารถเพิ่ม / อัปเดต / ลบบนตารางฐานของคุณและเพียงแค่สอบถามสถานการณ์ของมุมมองใหม่โดยไม่จำเป็นต้องสร้างอะไรขึ้นมาใหม่ ข้อมูลเปลี่ยนแปลงตลอดเวลา

มีการปิดการซื้อขายแน่นอน เนื่องจากมุมมองเป็นตารางเสมือนจริงและไม่ใช่ตาราง "จริง" (ฐาน) คุณจึงเรียกใช้แบบสอบถาม (อาจซับซ้อน) ทุกครั้งที่เข้าถึง ซึ่งอาจทำให้สิ่งต่างๆช้าลงเล็กน้อย แต่มันอาจจะไม่ ขึ้นอยู่กับหลายประเด็น (ขนาดและลักษณะของข้อมูลคุณภาพของสถิติในแค็ตตาล็อกระบบความเร็วของฮาร์ดแวร์ปริมาณการใช้งานและอื่น ๆ อีกมากมาย) คุณจะไม่รู้จนกว่าจะได้ลอง หาก (และเฉพาะในกรณีที่) คุณพบว่าประสิทธิภาพช้าอย่างไม่สามารถยอมรับได้คุณอาจดูตัวเลือกอื่น ๆ (มุมมองที่เป็นรูปธรรมสำเนาของตาราง ... อะไรก็ตามที่ซื้อขายพื้นที่สำหรับเวลา)


ฉันได้อัปเดตคำถามเพื่ออธิบายว่าทำไมฉันจึงไม่สามารถลบออกจากตารางเดิมได้
Rory

1

สร้างตารางใหม่โดยใช้การเลือกเพื่อดึงข้อมูลที่คุณต้องการ จากนั้นสลับตารางเก่ากับตารางใหม่

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.