我有一个相当简单的表用于驱动web映射应用程序的tile处理.
Column | Type | Modifiers
---------------+--------------------------+---------------------------------------------------------
id | integer | not null default
nextval('wmts_tiles_id_seq'::regclass)
tile_matrix | integer |
rowx | integer |
coly | integer |
geom | geometry(Geometry,27700) |
processed | smallint |
Indexes:
"wmts_tiles_pkey" PRIMARY KEY, btree (id)
"wmts_tiles_wmts_tile_matrix_x_y" UNIQUE CONSTRAINT, btree (tile_matrix, rowx, coly)
"ix_spatial_wmts_tiles" gist (geom)
"ix_tile_matrix_processed" btree (tile_matrix, processed)
Run Code Online (Sandbox Code Playgroud)
具有各种索引(一个空间)和如图所示的constaints.该表有2.4亿行,pg_relation_size和pg_total_relation_size表示该表为66 GB,其中一半是索引,一半是数据.
我添加了一个日期列,然后运行更新以填充它,
alter database wmts_tiles add column currency_date date;
update wmts_tiles set currency_date = '2014-05-01'
Run Code Online (Sandbox Code Playgroud)
在此之后,大小达到133 GB,即它增加了一倍.一旦我在桌面上运行VACUUM FULL,大小缩小到67 GB,即比以前大1GB,这是你在添加2.4亿行4字节字段(日期)后所期望的.
我知道在表中经常会有相当比例的死行,其中发生了大量的插入和删除,但为什么在单个更新下表的大小会翻倍并且我能做些什么来防止这种情况?请注意,此更新是唯一正在运行的事务,并且该表刚刚被转储并重新创建,因此数据页和索引在更新之前处于紧凑状态.
编辑:我已经看到了这个问题,为什么我的postgres表在更新时会变得更大?我理解,虽然表正在更新以支持MVCC,但表需要重写,我不明白为什么它保持两倍的大小,直到我明确地运行VACUUM FULL.
大多数问题都包含在前一个问题中.
它没有缩小的原因是PostgreSQL不知道你想要它.分配磁盘空间(增长表)然后重复释放(缩小表)是低效的.PostgreSQL更喜欢增长一个表,然后保留磁盘空间,将其标记为空并准备重新使用.
分配和发布周期不仅效率低下,而且OS也只允许在文件末尾释放空间*.因此,PostgreSQL必须将文件末尾的所有行移动到开始时现在可用空间,这是您在更新时可以写入的唯一位置.它无法执行此操作,因为在更新事务提交之前,它无法覆盖任何旧数据.
如果您知道不再需要空间,可以使用VACUUM FULL压缩表并释放空间.
有没有定期的真空被自动清理全面完成,部分原因是因为它可能是相当糟糕的表现,如果表只是必须再次扩大,部分原因是由于真空满是相当I/O密集型(所以它会减慢一切下降),部分因为vacuum full需要一个access exclusive锁来阻止对表的任何并发访问.PostgreSQL需要一个增量表重新打包命令/功能,它还没有,因为这可以通过autovacuum实现.修补程序是受欢迎的...虽然这部分代码非常复杂,但正确的做法并不适合初学者.
* 是的,我知道您可以将文件中的大区域标记为某些平台上的稀疏区域.随意提交PostgreSQL补丁.实际上你还是必须压缩,因为你没有在表中找到带有空闲页面的大区域.另外,您必须处理页眉.
| 归档时间: |
|
| 查看次数: |
2097 次 |
| 最近记录: |