2011-07-10 44 views
-1

我已經使用Postgres與我的Django項目一段時間了,但我從不需要使用存儲的函數。對於以下問題,找到最有效的解決方案非常重要:如何在Postgres中創建一個存儲函數更新行?

我有一張表,其中包含以下列: number | last_update | growth_per_second

而且我需要一個有效的解決方案根據last_update和增長因子更新數字,並將last_update值設置爲當前時間。我可能會有100個,也許有150K行。如果可能的話,我需要在同一時間更新所有行,但如果它需要很長時間,我可以將它分成較小的部分。

+1

如果您需要「同時」更新所有行,則應該查看事務而不是存儲過程/函數。 – Patrick

回答

1

快速存儲什麼你不能計算 。

您確定需要保存這些信息?如果是這樣,如果查詢速度慢,你能緩存嗎?通過嘗試在數據庫中保持此信息的一致性,您正在設置自己的表大意。

1

首先,如果你想要走這條路線,首先需要關於服務器編程的PostgreSQL文檔,然後根據你嘗試過的問題回來。你會想要熟悉這個領域,因爲取決於你在做什麼......

現在,假設你的數據是所有插入和沒有更新,我會而不是直接存儲這些信息在你的數據庫。如果它只是一小部分信息,那麼無論如何你都會得到索引掃描結果,如果你返回一個小小的結果集,你應該能夠快速計算出來。

相反,我會這樣做:讓你的last_update列成爲同一張表的外鍵。假設你的表如下所示:

CREATE TABLE hits (
    id bigserial primary key, 
    number_hits bigint not null, 
    last_update_id bigint references hits(id), 
    .... 
); 

然後我會創建以下函數。請注意以下警告。

CREATE FUNCTION last_update(hits) RETURNS hits IMMUTABLE LANGUAGE SQL AS $$ 
    SELECT * FROM hits WHERE id = $1.last_update_id; 
$$; 

此函數允許您在小的結果集上遍歷最後一條更新記錄。請注意,如果您保證在匹配表上沒有更新或刪除,那麼這裏的不可變名稱是唯一安全的。如果你這樣做,那麼你應該改變它穩定,你失去了索引輸出的能力。如果你做這個擔保,然後必須做一個更新,那麼你MUST重建使用這種(重新索引表命中)任何索引,這可能需要一段時間....

從這裏,我們可以:

CREATE FUNCTION growth(hits) RETURNS numeric immutable language sql as $$ 
    SELECT CASE WHEN ($1.last_update).number_hits = 0 THEN NULL 
       ELSE $1.number_hits/($1.last_update).number_hits 
      END; 
$$; 

然後,我們可以:

SELECT h.growth -- or alternatively growth(h) 
    FROM hits 
WHERE id = 12345; 

,它會自動計算。如果我們要對經濟增長進行搜索,我們可以索引輸出:

CREATE INDEX hits_growth_idx ON hits (growth(hits)); 

這將預先計算供搜索。這種方式如果你想做一個:

SELECT * FROM hits WHERE growth = 1; 

它可以使用索引掃描預定義的值。

當然,您可以使用相同的技術進行預先計算和存儲,但這種方法更加靈活,如果您必須使用大型結果集,則可以自行加入一次,並以這種方式計算,繞過您的功能。

相關問題