(本文阅读预计时间:5分钟)
文章转载自公众号:AustinDatabases
作者:carol11
最近有一位同学问关于修改字段为什么改大不rewrite table但是改小字段长度就会导致rewrite table,其实这就是PostgreSQL在修改字段上面有一个问题,这就是人尽皆知的rewrite,rewrite本身并没有什么错误的,但是如果在线进行大表的操作者就会引起表锁,导致业务中断。那问题来了,为什么会修改表的结构对于varchar从大到小,或者数据类型变化会导致rewrite table
上面这张图大家都熟悉,就是PostgreSQL的页面的图形,从上图看一个页面中下面是保存的行的数据,上面是item是存储空间分配的指针,这一行数据从哪里到哪里,头尾相接的一种数据结构。之前老版本的PostgreSQL无论是将字段由小改大还是反过来都是导致表的rewrite
那么我们需要验证PostgreSQL为什么在新版本中对于扩展不在进行重写而对于收缩还是会导致收缩。
我们通过逻辑分析来考虑
1. 通过item指针来进行行的分割的话,那么增加一个行的长度并没有触犯item的底线,因为之前的一行里面的字段长度是固定的也就是可以预分配这个空间,而如果我将varchar(30)改变为varchar(40)则原有的行都不需要变动,疑问都符合varchar(40)以内,所以只有后续的行的数据会进行会进行扩展,那就不会导致存储空间的溢出。所以以小改大都是可以的。
Field Type Length Offset Description
t_xmin TransactionId 4 bytes 0 insert XID stamp
t_xmax TransactionId 4 bytes 4 delete XID stamp
t_cid CommandId 4 bytes 8 insert and/or delete CID stamp (overlays with t_xvac)
t_xvac TransactionId 4 bytes 8 XID for VACUUM operation moving a row version
t_ctid ItemPointerData 6 bytes 12 current TID of this or newer row version
t_infomask2 uint16 2 bytes 18 number of attributes, plus various flag bits
t_infomask uint16 2 bytes 20 various flag bits
t_hoff uint8 1 byte 22 offset to user data
上图是一个表的信息,我看可以看到t_hoff是存储用户数据的地方
详情请查看网址:
https://www.programmersought.com/article/7081994849/
2. 如果是缩小字段会引起数据长度的变化和收缩,则会这样的情况下就需要重新写表,至少对先前定义的内容以及界限进行重新组织。
这点可以在tiemid.h找到一些线索
https://doxygen.postgresql.org/structItemIdData.html
其中itemid.h其中包含了lp_off lp_flags lp_len等几个data fields
https://medium.com/@djboris/postgresql-physical-storage-of-rows-da20a1389509
其中个图片对上面hexdump中的HEX:18进行了描述。
新闻|Babelfish使PostgreSQL直接兼容SQL Server应用程序
更多新闻资讯,行业动态,技术热点,请关注中国PostgreSQL分会官方网站
http://www.postgresqlchina.com
中国PostgreSQL分会生态产品
http://www.pgfans.cn
中国PostgreSQL分会资源下载站
http://postgreshub.cn
点击此处阅读原文
↓↓↓