Postgresql

縮放 PostgreSQL 觸發器

  • August 23, 2019

Postgres 如何觸發機制規模?

我們有一個大型 PostgreSQL 安裝,我們正在嘗試使用日誌表和 TRIGGER 實現基於事件的系統。

基本上,我們想為每個表創建一個 TRIGGER,我們希望收到 UPDATE/INSERT/DELETE 操作的通知。一旦觸發此觸發器,它將執行一個函式,該函式將簡單地將一個新行(對事件進行編碼)附加到一個日誌表中,然後我們將從外部服務輪詢該日誌表。

在全部使用 Postgres TRIGGER(s) 之前,我們想知道它們是如何擴展的:我們可以在單個 Postgres 安裝上創建多少個觸發器?它們會影響查詢性能嗎?有沒有人試過這個?

基本上,我們想為每個表創建一個 TRIGGER,我們希望收到 UPDATE/INSERT/DELETE 操作的通知。一旦觸發此觸發器,它將執行一個函式,該函式將簡單地將一個新行(對事件進行編碼)附加到一個日誌表中,然後我們將從外部服務輪詢該日誌表。

這是觸發器的標準用法。

在全部使用 Postgres TRIGGER(s) 之前,我們想知道它們是如何擴展的:我們可以在單個 Postgres 安裝上創建多少個觸發器?

如果您繼續創建它們,最終您將耗盡磁碟空間。

觸發器沒有具體限制。

PostgreSQL 限制記錄在 about page 上

它們會影響查詢性能嗎?

這取決於觸發器類型、觸發器語言以及觸發器的作用。

BEFORE ... FOR EACH STATEMENT一個不做任何事情的簡單 PL/PgSQL觸發器的成本幾乎為零。

FOR EACH ROW觸發器的成本高於FOR EACH STATEMENT觸發器。顯然,使用受影響的行數進行縮放。

AFTER觸發器比BEFORE觸發器更昂貴,因為它們必須排隊等待語句完成其工作,然後執行。如果隊列變大,它們不會溢出到磁碟(至少在 9.4 及更低版本中,將來可能會發生變化),因此巨大的AFTER觸發器隊列會導致可用記憶體溢出,從而導致語句中止。

在插入/更新之前修改NEW行的觸發器比執行 DML 的觸發器便宜。

您想要的特定案例通過正在進行的增強可能會更好地執行,這可能會使其進入 PostgreSQL 9.5(如果我們幸運的話),其中FOR EACH STATEMENT觸發器可以看到虛擬OLDNEW表。這在目前的 PostgreSQL 版本中是不可能的,因此您必須使用FOR EACH ROW觸發器。

有沒有人試過這個?

當然。這是觸發器的一個非常標準的用途,以及審計、健全性檢查等。

當任務表發生更改時,您需要研究LISTENNOTIFY找到一種喚醒工作人員的好方法。

通過避免直接從觸發器與外部系統對話,您已經在做最重要的事情。這往往會給性能和可靠性帶來問題。人們經常嘗試直接從觸發器發送郵件,這是個壞消息。

這是一個稍微遲到的答案,但它可能對未來的讀者有用

現在(在 10、11、12 版本中)我們不需要兩次儲存相同的數據(在 WAL 中由 PG 和手動)。我們可以使用 Postgre邏輯解碼機制(與邏輯複製相同)來跟踪我們數據的全部或部分更改(或將這些事件發送到像 kafka 這樣的隊列以便稍後分析)

引用自:https://dba.stackexchange.com/questions/88761