2012-12-08 46 views
4

我有一個postgresql數據庫和一個近億行的表。 當我嘗試用默認值添加一個新列:將具有默認值的列添加到一個巨大的表

ALTER TABLE big_table 
ADD COLUMN some_flag integer NOT NULL DEFAULT 0; 

交易正好爲30+分鐘..和數據庫日誌開始射擊警告。

任何方式來優化查詢?

+1

什麼警告給你在日誌文件中看到? –

+0

您可以使用其數據創建表的副本,將該列添加到該副本,然後通過重命名它們來交換這兩個表。 (您可能需要適當處理依賴關係) – dezso

+0

@dezso我們正在討論10億行繁忙的表... 如何複製它將使程序更快/更好 –

回答

6

除了分批做(這仍需要一段時間):

你可以轉儲表作爲COPY報表和編寫腳本編輯COPY語句的內容中插入另一列(COPY可CSV IIRC)。

然後,您只需重新加載已更改的COPY轉儲,理論上它應該比ALTER更快,因爲COPY不會記錄事務。

另一種選擇是在運行命令時關閉fsync ...只記得重新打開它。

您也可以批量執行上述兩項操作。

+0

謝謝,我希望更多的查詢構建技巧,但它似乎沒有。我將在下次考慮Fsync。 –

+0

在一天結束時,十億是十億。這不是一個小數字:)。我很好奇數據是什麼? –

+0

它表示來自RL文檔的解析數據。當然,有一個更好的存儲概念,但改變整個結構不是一種選擇。 –

4

我會考慮在沒有默認情況下創建列,並手動更新批處理中的行並間斷提交應用默認值。

+0

也在想同樣的事情,但最終可能需要更多時間。我需要把它放在「版本更新」交易中,所以我正在尋找一個更清潔的解決方案。 –

+1

需要複製單行或其他所有行才能在新列中獲取非空值。您可以一次完成所有操作,通過在'ALTER TABLE'中指定默認值來阻止其他訪問。當其他進程通過將該列添加爲空值並進行一系列小更新(可能在迭代之間有睡眠)時,您可以逐步執行此操作。不要在整個表的一個大的'UPDATE'中做,否則你會膨脹表。 – kgrittn

+0

爲了最有效,您還需要在每批之間進行VACUUM。 – carbocation

相關問題