Eva*_*oll 4 postgresql index locking
在此问题之后,是否更改varchar()
表重写或锁定比更改CHECK
约束花费更多时间的结果的长度限制(类型修饰符)?从那个问题你可以看到Brandur 的说法,
如果您想更改长度,则
ALTER TABLE
需要排他锁(请参阅https://www.postgresql.org/docs/current/static/sql-altertable.html ...)。改变CHECK
是即时的。在回答一个问题,质疑文CHECK (char_length(email) <= 255)
VSvarchar(255)
似乎这可能起源于 Depesz 在 2010 年发表的帖子“CHAR(X) VS. VARCHAR(X) VS. VARCHAR VS. TEXT – 2010-03-03 更新”
那么,当你[使用 varchar] 使限制更大时会发生什么?
PostgreSQL 必须重写该表。这有两个非常重要的缺点: 1. 操作时需要对表进行排他锁 2. 在非平凡表的情况下,将花费相当多的时间
您可以在此处 (2017)的评论中再次看到这一点,
尽管如此,当我想将我
VARCHAR(50)
的VARCHAR(250)
.
再次在这里(2012),
顺便说一句:如果可以避免的话,我从不使用 varchar - 特别是不使用长度修饰符。它几乎提供了类型文本无法提供的任何内容。如果我需要长度限制,我会使用一个列约束,它可以在不重写整个表的情况下进行更改。
显然还有其他人怀疑这一说法。
仅仅解决这个单一的要求可能是值得的。
本质上,这是过时的信息。从 9.2 开始就不再相关了。现在,我能看到的唯一缺点是,如果长度约束变得更加严格并且必须重新检查,则索引会被重写。
在 9.1 的发行说明中,正如 Erwin 所发现的那样
允许
ALTER TABLE ... SET DATA TYPE
在适当的情况下避免表重写(Noah Misch,Robert Haas)例如,将 varchar 列转换为文本不再需要重写表。但是,增加 varchar 列的长度约束仍然需要重写表。
在 9.2 的发行说明中,正如@a_horse_with_no_name 所发现的那样,
减少为某些
ALTER TABLE ... ALTER COLUMN TYPE
操作重建表和索引的需要(Noah Misch)增加 varchar 或 varbit 列的长度限制,或完全删除限制,不再需要重写表。同样,增加数值列的允许精度,或将列从受约束的数值更改为不受约束的数值,不再需要重写表。在涉及间隔、时间戳和时间戳记类型的类似情况下,也可以避免表重写。
上的文档ALTER
有这个说法
添加带有
DEFAULT
子句的列或更改现有列的类型将需要重写整个表及其索引。作为更改现有列的类型时的一个例外,如果USING
子句不更改列内容并且旧类型可以二进制强制转换为新类型或新类型上的不受约束的域,则不需要重写表;但仍必须重建受影响列上的任何索引。添加或删除系统 oid 列也需要重写整个表。对于大表,表和/或索引重建可能需要大量时间;并且将暂时需要多达两倍的磁盘空间。
下面是我修改的 a_horse_with_no_name 提供的测试用例,让我们看看它的实际效果。
\timing 1
CREATE TABLE alter_test (id int primary key, some_data varchar(50));
INSERT INTO alter_test
SELECT i, md5(i::text)
FROM generate_series(1,1e7) AS gs(i);
ALTER TABLE alter_test
ALTER COLUMN some_data
TYPE varchar(55);
Time: 5.671 ms
Run Code Online (Sandbox Code Playgroud)
所以我们没有索引就不会减速。然后我们添加一个索引,然后再试一次,
CREATE INDEX ON alter_test (some_data);
ALTER TABLE alter_test
ALTER COLUMN some_data
TYPE varchar(55);
Time: 6.423 ms
Run Code Online (Sandbox Code Playgroud)
我VACUUM FULL ANALYZE
在桌子上试了一下,varchar
又把长度拉长了,还是没花更多时间。并不是说它在所有情况下都被很好地揭穿,但至少在简单的情况下,即使在索引时,如果您要使约束不那么严格,这似乎也不是问题。但是,使长度约束更具限制性似乎正在做一些事情。
ALTER TABLE alter_test
ALTER COLUMN some_data
TYPE varchar(50);
ALTER TABLE
Time: 59690.885 ms
Run Code Online (Sandbox Code Playgroud)
删除索引并再次尝试要快得多,
DROP INDEX alter_test_some_data_idx ;
DROP INDEX
Time: 85.978 ms
test=# ALTER TABLE alter_test
ALTER COLUMN some_data
TYPE varchar(49);
ALTER TABLE
Time: 9297.271 ms
Run Code Online (Sandbox Code Playgroud)
因此,似乎只有当长度约束变得更加严格并且必须重新验证时,索引才会被重写。
归档时间: |
|
查看次数: |
3464 次 |
最近记录: |