免责声明:此问题类似于堆栈溢出问题here,但这些问题都不适合我的问题,我稍后会解释。
我正在尝试在postgres中复制一个大表(大约40M行,100多列),其中很多列都被索引。目前我使用这个SQL:
CREATE TABLE <tablename>_copy (LIKE <tablename> INCLUDING ALL);
INSERT INTO <tablename>_copy SELECT * FROM <tablename>;
此方法有两个问题:
表格大小使索引成为实时问题。它还使得转储到文件然后重新摄取是不可行的。我也没有命令行的优势。我需要在SQL中执行此操作。
我想要做的是直接用奇迹命令制作精确副本,或者如果不可能的话,复制具有所有约束但没有索引的表,并确保它们是精神上的约束' '(又称SERIAL列的新计数器)。然后使用SELECT *
复制所有数据,然后复制所有索引。
来源
Stack Overflow question about database copying:这不是我要求的原因有三个原因
pg_dump -t x2 | sed 's/x2/x3/g' | psql
,在此设置中,我无权访问命令行default nextval('x1_id_seq'::regclass)
Method to reset the sequence value for a postgres table:这很棒,但不幸的是它是非常手动的。
答案 0 :(得分:53)
答案 1 :(得分:45)
PostgreSQL中的create table as
功能现在可能是OP正在寻找的答案。
https://www.postgresql.org/docs/9.5/static/sql-createtableas.html
create table my_table_copy as
select * from my_table
这将创建一个与数据相同的表。
添加with no data
将复制没有数据的架构。
create table my_table_copy as
select * from my_table
with no data
这将创建包含所有数据的表,但没有索引和触发器等。
create table my_table_copy (like my_table including all)
类似语法的create table将包括所有触发器,索引,约束等。但不包括数据。
答案 2 :(得分:14)
最接近的“奇迹命令”就像是
pg_dump -t tablename | sed -r 's/\btablename\b/tablename_copy/' | psql -f -
特别是,这需要在加载表数据后创建索引。
但这不会重置序列;你必须自己编写脚本。
答案 3 :(得分:4)
要完全复制一个表,包括表结构和数据,请使用以下语句:
CREATE TABLE new_table AS
TABLE existing_table;
要复制不包含数据的表结构,可将WITH NO DATA子句添加到CREATE TABLE语句中,如下所示:
CREATE TABLE new_table AS
TABLE existing_table
WITH NO DATA;
要从现有表中复制包含部分数据的表,请使用以下语句:
CREATE TABLE new_table AS
SELECT
*
FROM
existing_table
WHERE
condition;
答案 4 :(得分:2)
警告:强>
使用pg_dump和任何类型的正则表达式替换源表名称的所有答案都非常危险。如果您的数据包含您要替换的子字符串,该怎么办?您最终会更改数据!
我建议采用双程解决方案:
这是一个用Ruby编写的例子:
ruby -pe 'gsub(/(members?)/, "\\1_copy_20130320") unless $_ =~ /^\d+\t.*(?:t|f)$/' < members-production-20130320.sql > copy_members_table-20130320.sql
在上面我试图将“members”表复制到“members_copy_20130320”中。我的数据特定正则表达式是/ ^ \ d + \ t。*(?:t | f)$ /
以上类型的解决方案适合我。告诫者......
修改强>
好的,这是针对正则表达式反义词的伪shell语法的另一种方式:
psql -f mytable_copy_schema.sql mydb
pg_dump -a -t mytable mydb&gt; mytable_data.sql
答案 5 :(得分:0)
显然你想“重建”一张桌子。如果您只想重建一个表而不是复制它,那么您应该使用CLUSTER。
SELECT count(*) FROM table; -- make a seq scan to make sure the table is at least
-- decently cached
CLUSTER someindex ON table;
您可以选择索引,尝试选择适合您查询的索引。如果没有其他索引适合,您始终可以使用主键。
如果你的表太大而无法缓存,那么CLUSTER可能会很慢。
答案 6 :(得分:-1)
create table newTableName(就像包含索引的oldTableName); 插入newTableName select * from oldTableName
这对我有用9.3