2011-03-14 28 views
1

當我有如下表:如何通過更新來避免零散的數據庫存儲?

CREATE TABLE test 
(
    "id" integer NOT NULL, 
    "myval" text NOT NULL, 
    CONSTRAINT "test-id-pkey" PRIMARY KEY ("id") 
) 

當做了很多類似下面的查詢:

UPDATE "test" set "myval" = "myval" || 'foobar' where "id" = 12345 

然後該行會設爲myVal隨着時間的推移越來越大。 postgresql會做什麼?它將從哪裏獲得空間?

我可以避免postgresql需要多個seek來讀取特定的myval-column嗎?

postgresql會自動執行此操作嗎?

我知道,通常我應該嘗試正常化數據更多。但我需要一次尋求閱讀價值。每次更新時Myval會放大約20個字節(即增加數據)。一些colums將有1-2次更新,大約1000次更新。 通常我只是使用一個新行而不是更新。但是,選擇正在變得緩慢。 所以我想到了反規範化的想法。

+0

我不明白這個問題,但有了合適的索引,速度不應該成爲問題。此外,由於最終的行數較少,所以將值添加到現有列值的方式比添加新行要複雜得多,但這些行數會更大,因此速度更慢。此外,查詢沒有正確引用(僅供參考以節省一些錯誤)。 – DrColossos 2011-03-14 16:12:31

+0

正是這個問題。數據庫用更新來存儲這些值有多複雜? postgresql會讀取舊數據並將其複製到新的位置?這是如何從postgresql管理的? – Chris 2011-03-14 16:30:28

回答

3

更改表的FILLFACTOR以創建未來更新的空間。這也可以是HOT更新,因爲文本字段沒有索引,使更新更快,自動清理開銷更低,因爲HOT更新使用微型真空。 CREATE TABLE語句包含有關FILLFACTOR的一些信息。

ALTER TABLE test SET (fillfactor = 70); 
-- do a table rebuild to blow some space in your current table: 
VACUUM FULL ANALYZE test; 
-- start testing 

值70不是一個完美的設置,它取決於你的獨特情況。也許你在90歲時很好,也可能是40歲或者別的什麼東西。

1

這與TEXT in PostgreSQL這個問題有關,或者至少答案是相似的。 PostgreSQL stores large columns遠離主表存儲:

非常長的值也存儲在背景表中,因此它們不會影響快速訪問較短的列值。

所以你可以期待一個TEXT(或BYTEA或大VARCHAR)列總是從主表和像SELECT id, myval FROM test WHERE id = 12345東西保存起來會採取兩種試圖拉兩列從磁盤(多尋求解決他們的位置)。

如果您的更新確實導致您的SELECT速度變慢,那麼您可能需要檢查一下您的vacuuming策略。

+0

將值存儲在背景表格中時,當更新此值時會發生什麼情況。它會被讀取,然後再次存儲,或只是添加? – Chris 2011-03-14 16:55:56

+0

@Chris:據推測,它必須複製並修改它,否則它將無法正確隔離任何交易生效的變更;我不認爲PostgreSQL有這種情況的任何花哨的版本控制系統,但我不確定。然後通常的吸塵過程將清理舊的過時副本。 – 2011-03-14 19:51:58