在postgres中复制一个表(包括索引)
我有一个postgres表。 我需要从中删除一些数据。 我要创build一个临时表,复制数据,重新创build索引,并删除我需要的行。 我不能从原始表中删除数据,因为这个原始表是数据的来源。 在一种情况下,我需要得到一些依赖于删除X的结果,在另一种情况下,我需要删除Y.所以我需要所有的原始数据总是可用的。
但是,重新创build表并将其复制并重新创build索引似乎有点愚蠢。 有没有在postgres告诉它“我想要一个完整的单独的副本,这个表,包括结构,数据和索引”?
不幸的是,PostgreSQL没有“CREATE TABLE .. LIKE X INCLUDING INDEXES”
新的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)
正如你所看到的,我正在testing8.3。
现在,我们来创build表格:
# 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 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)
[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';
从第一个创build一个新表的另一种方法是使用
CREATE TABLE films_recent (LIKE films INCLUDING INDEXES); INSERT INTO films_recent SELECT * FROM books WHERE date_prod >= '2002-01-01';
请注意,如果使用第二种方法,Postgresql有一个修补表空间问题的补丁
我有一个postgres表。 我需要从中删除一些数据。
我认为…
delete from yourtable where <condition(s)>
…由于某种原因不起作用。 (小心分享这个理由?)
我要创build一个临时表,复制数据,重新创build索引,并删除我需要的行。
看看pg_dump和pg_restore。 使用pg_dump与一些聪明的select,也许编辑输出之前,pg_restoring可能会做的伎俩。
既然你正在对数据进行“如果”types的分析,我想知道你是否可以更好地使用视图。
您可以根据您要排除的内容的否定来为每个要testing的scheme定义一个视图。 也就是说,根据你想要包含的内容定义一个视图。 例如,如果你想在“删除”X = Y行的数据上有一个“窗口”,那么你可以创build一个视图为行(X!= Y)。
视图作为其定义查询存储在数据库(在系统目录中)中。 每次查询视图时,数据库服务器都会查找定义该视图的基础查询并执行该查询(与您使用的任何其他条件进行“与”运算)。 这种方法有几个好处:
- 你永远不会复制你的数据的任何部分。
- 查询每个视图/场景时,将使用已经用于基表(您的原始“真实”表)的索引(查询优化器认为合适)。 没有必要重新定义或复制它们。
- 由于视图是基表中“真实”数据的“窗口”(而非shapshot),因此您可以在基表上添加/更新/删除,只需重新查询视图场景,而不需要重新创build任何数据随时间变化。
当然有一个权衡。 由于一个视图是一个虚拟表,而不是一个“真正的”(基)表,你实际上每次访问时都会执行一个(也许是复杂的)查询。 这可能会减慢一点。 但它可能不会。 这取决于许多问题(数据的大小和性质,系统目录中的统计质量,硬件速度,使用负载等等)。 直到你尝试之后你才会知道。 如果(且只有)你确实发现性能是不可接受的缓慢,那么你可以看看其他的select。 (物化视图,表格副本……任何时间交换空间的东西)
使用select创build一个新表来获取所需的数据。 然后将旧表与新表交换。
create table mynewone as select * from myoldone where ... mess (re-create) with indexes after the table swap.