Скопировать таблицу (включая индексы) в postgres - PullRequest
79 голосов
/ 13 октября 2008

У меня есть таблица postgres. Мне нужно удалить некоторые данные из него. Я собирался создать временную таблицу, скопировать данные, воссоздать индексы и удалить нужные мне строки. Я не могу удалить данные из исходной таблицы, потому что эта исходная таблица является источником данных. В одном случае мне нужно получить некоторые результаты, которые зависят от удаления X, в другом случае мне нужно будет удалить Y. Поэтому мне нужно, чтобы все исходные данные всегда были рядом и были доступны.

Однако, кажется немного глупым воссоздать таблицу, скопировать ее снова и воссоздать индексы. Есть ли что-то в postgres, чтобы сказать: «Мне нужна полная отдельная копия этой таблицы, включая структуру, данные и индексы»?

К сожалению, в PostgreSQL нет "CREATE TABLE .. LIKE X с индексами"

Ответы [ 4 ]

100 голосов
/ 03 июля 2009

Новый PostgreSQL (начиная с версии 8.3 согласно документации) может использовать «ВКЛЮЧАЯ ИНДЕКСЫ»:

# 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)
42 голосов
/ 14 октября 2008
[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 есть патч для устранения проблем табличного пространства, если используется второй метод

4 голосов
/ 14 октября 2008

У меня есть таблица postgres. Мне необходимо удалить некоторые данные из него.

Полагаю, что ...

delete from yourtable
where <condition(s)>

... по какой-то причине не сработает. (Хотите поделиться этой причиной?)

Я собирался создать временный таблицу, скопируйте данные в, воссоздайте индексы и удалить строки я необходимо.

Посмотрите на pg_dump и pg_restore. Использование pg_dump с некоторыми умными опциями и, возможно, редактирование вывода перед pg_restoring может помочь.


Поскольку вы проводите анализ данных типа "что, если", я хотел бы знать, не лучше ли вам использовать представления.

Вы можете определить представление для каждого сценария, который вы хотите проверить, основываясь на отрицании того, что вы хотите исключить. Т.е., определить представление на основе того, что вы хотите включить. Например, если вам нужно «окно» в данных, где вы «удалили» строки, где X = Y, то вы бы создали представление в виде строк, где (X! = Y).

Представления хранятся в базе данных (в системном каталоге) в качестве определяющего запроса. Каждый раз, когда вы запрашиваете представление, сервер базы данных ищет базовый запрос, который его определяет, и выполняет его (И с любыми другими используемыми вами условиями). У этого подхода есть несколько преимуществ:

  1. Вы никогда не дублируете какую-либо часть своих данных.
  2. Индексы, которые уже используются для базовой таблицы (вашей исходной «реальной» таблицы), будут использоваться (как это будет сочтено подходящим для оптимизатора запросов) при запросе каждого представления / сценария. Нет необходимости переопределять или копировать их.
  3. Поскольку представление является «окном» (НЕ шейпшотом) для «реальных» данных в базовой таблице, вы можете добавлять / обновлять / удалять в своей базовой таблице и просто повторно запрашивать сценарии представления без необходимости воссоздайте что угодно, так как данные меняются со временем.

Конечно, есть компромисс. Поскольку представление является виртуальной таблицей, а не «реальной» (базовой) таблицей, вы фактически выполняете (возможно, сложный) запрос каждый раз, когда получаете к нему доступ. Это может немного замедлить ход событий. Но это не так. Это зависит от многих проблем (размер и характер данных, качество статистики в системном каталоге, скорость аппаратного обеспечения, нагрузка на использование и многое другое). Вы не узнаете, пока не попробуете. Если (и только если) вы на самом деле обнаружите, что производительность неприемлемо низкая, вы можете посмотреть на другие варианты. (Материализованные представления, копии таблиц, ... все, что меняет пространство на время.)

1 голос
/ 13 октября 2008

Создайте новую таблицу с помощью выбора, чтобы получить нужные данные. Затем замените старый стол новым.

create table mynewone as select * from myoldone where ...
mess (re-create) with indexes after the table swap.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...