2010-04-08 50 views
1

由於Postgres只能在表格末尾添加列,所以我最終通過在表格末尾添加新列,將它們設置爲等於現有列,然後刪除原始列來重新排序。對PostgreSQL中的列重新排序的記錄大小有什麼影響?

那麼,PostgreSQL是如何處理被丟棄列釋放的內存的呢?它是否會自動重新使用內存,因此單個記錄消耗與以前相同的空間量?但是這需要重寫整個表格,所以爲了避免這種情況,它是否會在每條記錄中留下一堆空白空間?

回答

1

docs

DROP COLUMN形式不物理刪除列,但只是讓無形的SQL操作。表中的後續插入和更新操作將爲該列存儲空值。因此,刪除列很快,但不會立即減少表中的磁盤大小,因爲所刪除的列所佔用的空間不會被回收。隨着現有行的更新,空間將隨着時間的推移而被回收。

您需要先執行CLUSTER後跟VACUUM FULL才能回收空間。

+2

真空FULL如果每行更新將只回收空間,這完全死亡後行清理 - 另有好行沒有死列。由於設置新列的UPDATE必須在執行DROP之前發生,因此現在已過時的列佔用的空間將不會被它收回。只有該行的原始副本將被清除。 除了完全更新之外,您還可以執行CLUSTER(在PostgreSQL 8.3或更高版本中)或創建表的全新副本(類似於CREATE TABLE AS),然後對名稱進行隨機洗牌以實際消除死亡空間列。 – 2010-04-10 00:46:26

+0

@Greg:好的一點。 – Quassnoi 2010-04-10 18:21:09

+0

@Summer:'CLUSTER'重寫整個表格(加上索引),從而完美地優化它。 'CLUSTER'後面的'VACUUM FULL'是多餘的。你可能想要運行'ANALYZE'。這個答案是不正確的(報價除外)。我添加了一個答案來澄清。 – 2015-04-10 18:29:59

1

你爲什麼「重新訂購」?在SQL中沒有順序,它沒有建立起來。如果你需要一個固定的訂單,告訴你的查詢你需要什麼順序或使用一個視圖,這是什麼意見。

Diskspace將在真空後再次使用,auto_vacuum將完成這項工作。除非你禁用了這個過程。

你目前的方法會殺死整體性能(表鎖),索引必須重新創建,統計數據下到廁所等等。最後,你最終會遇到同樣的情況。那麼爲什麼這樣做呢?

+0

我期待這個來。我喜歡我的專欄,以便像我一樣對人類有意義。只要它不佔用太多的磁盤空間(在真空滿後它不會佔用太多空間)。只是個人喜好。 :) – Summer 2010-04-08 17:19:28

+2

您不應該依賴隱式列排序,就像不應該依賴隱式行排序而不使用ORDER BY。這是否意味着您的應用程序使用SELECT *和INSERT INTO表VALUES,而沒有字段名?因爲那只是要求麻煩。如果您想要特定的列順序,請使用該順序創建一個視圖。 – MkV 2010-04-09 08:55:18

+0

我需要重新排序,因爲將某些列組合起來更簡單!我無法相信像Postgres這樣基本的東西是不被支持的......課程我不依賴表中列的順序,但是在設計數據庫時它更容易!爲什麼所有這些linux讀者都不明白這一點?!現在人們使用GUI!這是2011年! – Dylan 2011-02-19 12:48:11

1

問題是舊的,但既然這兩個答案都是錯誤或誤導,我會再添加一個。

當更新一行時,Postgres寫入一個新的行版本,舊的版本最終在VACUUM之後被刪除,沒有運行的事務可以再看到它。

Plain VACUUM不會從包含表的物理文件向系統返回磁盤空間,除非它在表的物理端找到完全死或空的塊。您需要運行VACUUM FULLCLUSTER來積極壓縮表格並將多餘的空間返回給系統。這在正常操作中通常不是理想的。 Postgres可以重新使用死元組來保持同一數據頁面上的新行版本,這有利於性能。

在你的情況,由於你更新每一行,表的大小加倍(從它的最小大小)。建議運行VACUUM FULLCLUSTER將膨脹返回到系統。
兩個都在桌子上獨佔鎖。如果幹擾併發訪問,請考慮pg_repack,這可以在不使用排他鎖的情況下執行相同的操作。

澄清:運行CLUSTER完全回收空間。No VACUUM FULL is needed after CLUSTER (and vice versa).

更多細節:

相關問題