我在PostgreSQL中有一个表,其中两列包含图像作为文本(不是我的决定..)。因此,现在我不需要这些列,并且打算删除它们。但是,当我想估计删除列的“效果”(即表的大小将改变多少)时,我遇到了一个问题。 问题在于PostgreSQL显示的旧表和新表大小相同。这很奇怪,因为我要删除两个“重”列。
这是比较代码:
-- Create two copies of the table
CREATE TABLE oldwords (LIKE "words" INCLUDING INDEXES);
INSERT INTO oldwords SELECT * FROM "words";
CREATE TABLE newwords (LIKE "words" INCLUDING INDEXES);
INSERT INTO newwords SELECT * FROM "words";
-- Drop columns containing images
ALTER TABLE "newwords"
DROP COLUMN image_black,
DROP COLUMN image_colored;
-- Update stats of the tables
VACUUM ANALYZE "oldwords";
VACUUM ANALYZE "newwords";
-- Compare size
SELECT
relname as "Table",
pg_size_pretty(pg_total_relation_size(relid)) As "Size",
pg_size_pretty(pg_total_relation_size(relid) -
pg_relation_size(relid)) as "External Size"
FROM pg_catalog.pg_statio_user_tables
WHERE relname LIKE '___words'
ORDER BY pg_total_relation_size(relid) DESC
-- RESULT
Table Size External Size
newwords 296 MB 205 MB
oldwords 296 MB 205 MB
我做错什么了吗?为什么尺寸相同?正确的方法是什么?
答案 0 :(得分:4)
来自ALTER TABLE
:
“ DROP COLUMN”表单不会物理删除列,而只是删除 使其对SQL操作不可见。随后的插入和更新 表中的操作将为该列存储一个空值。
因此, 删除列很快,但不会立即减少 表的磁盘大小,作为删除磁盘所占用的空间 列未回收。随着时间的推移,该空间将被回收 现有行将更新。(这些语句在以下情况下不适用 删除系统oid列;立即完成 重写。)
要强制立即回收被删除的列占用的空间,您可以执行ALTER TABLE的一种形式来重写整个表。这样就可以重建每一行,并将删除的列替换为空值。