Mat*_*hia 11 postgresql database-design alter-table postgresql-9.1
我在表上添加新列时遇到问题。
我尝试运行了几次,但是运行了 10 多分钟后,由于锁定时间,我决定取消查询。
ALTER TABLE mytable ADD mycolumn VARCHAR(50);
Run Code Online (Sandbox Code Playgroud)
有用的信息:
我发现了有关 PostgreSQL 管理可空列的方式的有趣信息(通过 HeapTupleHeader)。
我的第一个猜测是,因为这个表已经有 32 个 8 位的可空列MAXALIGN, HeapTupleHeader 是 4 字节长度(未验证,我不知道如何这样做)。
因此,添加新的可为空的列可能需要在每一行上更新 HeapTupleHeader 以添加新的 8-bits MAXALIGN,这可能会导致性能问题。
因此,我尝试更改可空列之一(实际上并不是真正可以为空的),以便将可空列的数量减少到 31,以检查我的猜测是否属实。
ALTER TABLE mytable ALTER myothercolumn SET NOT NULL;
Run Code Online (Sandbox Code Playgroud)
不幸的是,这个改动也需要很长时间,超过5分钟,所以我也中止了。
您知道是什么导致了这种性能成本吗?
这里有几个误解:
的空位图是不堆元组报头的一部分。根据文档:
有一个固定大小的头(在大多数机器上占用 23 个字节),后跟一个可选的空位图......
由于两个原因,您的 32 个可空列是不可疑的:
每行添加空位图,并且仅当该行中至少有一个实际NULL值时。可空列没有直接影响,只有实际NULL值有影响。如果分配了空位图,则它总是完全分配(全部或全部)。空位图的实际大小是每列 1 位,四舍五入到下一个字节。每个当前源代码:
#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
Run Code Online (Sandbox Code Playgroud)空位图在堆元组头之后分配,后跟可选的 OID,然后是行数据。OID 或行数据的开始由t_hoff标头中的表示。每个评论源代码:
请注意,t_hoff 必须是 MAXALIGN 的倍数。
heap tuple header后面有1个空闲字节,占23个字节。因此,最多8列的行的空位图有效地无需额外成本。对于表中的第 9 列,将增加t_hoff另一个MAXALIGN(通常为 8 个)字节以提供另外 64 列。所以下一个边界是72列。
要显示 PostgreSQL 数据库集群(包括MAXALIGN)的控制信息,以在 Debian 机器上典型安装 Postgres 9.3 的示例:
sudo /usr/lib/postgresql/9.3/bin/pg_controldata /var/lib/postgresql/9.3/main
Run Code Online (Sandbox Code Playgroud)
我更新了 了您引用的相关答案中的说明。
除此之外,即使您的ALTER TABLE语句触发了整个表的重写(它可能会更改数据类型),250K 确实不是那么多,并且在任何中途体面的机器上只需几秒钟(除非行异常大) . 10 分钟或更长时间表示完全不同的问题。您的语句很可能正在等待获得表上的锁定。
越来越多的条目 pg_stat_activity意味着更多的开放事务 - 表明对表的并发访问(最有可能)必须等待操作完成。
检查可能的表膨胀,尝试温和的VACUUM mytable或更积极的VACUUM FULL mytable- 这可能会遇到相同的并发问题,因为这种形式也获得了排他锁。你可以试试pg_repack代替...
我将首先检查索引、触发器、外键或其他约束的可能问题,尤其是那些涉及列的问题。特别是可能涉及损坏的索引?尝试REINDEX TABLE mytable;或DROP所有这些,然后ALTER TABLE 在同一事务中重新添加它们。
尝试在夜间或负载不大的时候运行该命令。
一种蛮力方法是停止对服务器的访问,然后再试一次:
如果无法确定,升级到当前版本或即将推出的 9.4可能会有所帮助。对大表和锁定细节进行了多项改进。但是,如果您的数据库中出现问题,您可能应该先弄清楚。
| 归档时间: |
|
| 查看次数: |
4025 次 |
| 最近记录: |