ALTER COLUMN TYPE varchar(N)是否重写了Postgres 9.6中的表格?

时间:2018-02-08 19:30:37

标签: postgresql ddl varchar postgresql-9.6

过去

我们使用Postgres 8.4处理此问题的方法是手动更新<button ion-button color="light" onclick="window.open('https://mywebsite.com/offer?id=' + {{ proposal.id }}, '_self')">Offert</button> 表:

pg_attribute

LOCK TABLE pg_attribute IN EXCLUSIVE MODE; UPDATE pg_attribute SET atttypmod = 104 WHERE attrelid = 'table_name'::regclass AND attname = 'column_name'; 是一个column_name,我们想要一个varchar(50),但是这个表格太大了(数千万行),并且过于习惯于重写。

如今

围绕这个主题的内容和答案很少,并且对于这样一个(至少是有趣的)常见问题已经过时了。

但是,在看到至少3次讨论可能就是这种情况的暗示之后,我开始认为对于Postgres的新版本(我们使用的是9.6),您现在可以运行以下内容: / p>

varchar(100)

...无需重写表格。

这是正确的吗?

如果是这样,你知道Postgres文档中哪些关于该主题的确切信息存在吗?

2 个答案:

答案 0 :(得分:2)

ALTER TABLE不需要重写。

The documentation说:

  

添加带有DEFAULT子句的列或更改现有列的类型将需要重写整个表及其索引。

测试非常简单:
尝试使用空表,查看表的relfilenode行中的pg_class列是否发生更改:

SELECT relfilenode FROM pg_class
    WHERE relname = 'table_name';

在文档中阅读,您会看到:

  

作为例外,当更改现有列的类型时,如果USING子句不更改列内容,并且旧类型对新类型是二进制可强制的,或者对新类型是无约束域,不需要重写表格;但仍必须重建受影响列上的任何索引。

由于varchar(50)varchar(100)显然是二进制可强制的,因此您的情况不需要重写表,因为上述测试应该确认。

答案 1 :(得分:2)

根据What's new in PostgreSQL 9.2 上面的答案至少对我来说很奇怪接受的答案经过编辑以符合以下要求:

  

减少ALTER TABLE重写

     

在此期间,表将不再被重写   在以下更改列类型时的ALTER TABLE   情况:

     当y> = x 时,将

varchar(x)转换为varchar(y)。如果从   varchar(x)转换为varchar或文本(无大小限制)

我使用Postgres 10.4进行了测试,并且 relfilenode 在运行#!/bin/sh # Docker entrypoint (pid 1), run as root [ "$1" = "mongod" ] || exec "$@" || exit $? # Make sure that database is owned by user mongodb [ "$(stat -c %U /data/db)" = mongodb ] || chown -R mongodb /data/db # Drop root privilege (no way back), exec provided command as user mongodb cmd=exec; for i; do cmd="$cmd '$i'"; done exec su -s /bin/sh -c "$cmd" mongodb

后保持不变
alter table ... alter column ... type varchar(50)

我不确定为什么您在9.6中有一个不同的relfilenode(或者我错过了某些东西...)。