Postgresql

9000張表的PostgreSQL數據庫記憶體使用量持續增長

  • November 23, 2020

我有一個 PostgreSQL 數據庫,用於儲存時間序列(財務)數據。每個表都包含相同的表架構,但根據市場對和時間範圍具有不同的名稱。

前任。我有名為candles_btc_usdt_one_minute, candles_eth_usdt_one_hour,candles_eth_usdt_one_week等的表。

這些表總計大約 9000 個表。

請注意,我知道TimescaleDBand InfluxDB,我已經測試了兩者,並將在本文末尾發布我不使用它們的原因。

所以,由於這是時間序列數據,這意味著我只做INSERT寫操作,很少有人SELECT檢索一些數據。

我的問題是數據庫記憶體使用量似乎無限增長,直到我遇到 OOM 崩潰。我將我的postgresql.conf使用解決方案配置為PGTune具有 1GB RAM、6 個核心和 120 個連接的系統,並且我將我的 docker 容器限制為 4GB,並且在系統開啟大約一天后仍然得到 OOM。

我還嘗試了其他配置,例如容器中的 4GB 記憶體和 8GB,但 PostgreSQL 從不遵守配置規定的限制,並繼續使用越來越多的記憶體。

這是預期的行為嗎?也許 PostgreSQL 有一些其他晦澀的配置,我可以在有大量表的情況下使用它來限制記憶體使用量.. 我不確定..

我猜測這個問題與我的大量表有關的原因是因為我的連接池中打開的連接在我的系統啟動時(最初幾個小時)的記憶體使用量不斷增長,然後增長變慢(但永遠不會停止)。

這種行為反映了我INSERT在打牌時的間隔。

例如,具有時間範圍的表five_minutes意味著每五分鐘我將向其中插入一個新行,這意味著當系統啟動時我第一次訪問這些表時比具有更高時間範圍的表更快one_hour,等等。

並且監控記憶體增長,第一次訪問新表時,似乎連接程序增長了一點。

因此,假設這是正確的,這意味著幾個月後,所有連接將至少訪問所有表一次,並且記憶體增長將停止。這樣做的問題是我不知道這最終會使用多少記憶體,這並不理想,因為試圖通過限制記憶體postgresql.conf變得毫無意義。

這是其中一張表的架構(正如我之前所說,所有表都有相同的列、索引等):

data_db_prod=# \d+ candles_one_minute_btc_usdt
                                  Table "public.candles_one_minute_btc_usdt"
 Column   |            Type             | Collation | Nullable | Default | Storage | Stats target | Description 
-----------+-----------------------------+-----------+----------+---------+---------+--------------+-------------
timestamp | timestamp without time zone |           | not null |         | plain   |              | 
open      | numeric                     |           | not null |         | main    |              | 
close     | numeric                     |           | not null |         | main    |              | 
high      | numeric                     |           | not null |         | main    |              | 
low       | numeric                     |           | not null |         | main    |              | 
volume    | numeric                     |           | not null |         | main    |              | 
Indexes:
   "candles_one_minute_btc_usdt_timestamp_desc_index" btree ("timestamp" DESC)
   "candles_one_minute_btc_usdt_timestamp_index" btree ("timestamp")
Access method: heap

關於其他解決方案

正如我之前所說,我已經嘗試過TimescaleDB並且InfluxDB.

因為TimescaleDB我將能夠使用單個candles表並創建 2 個分區來儲存市場對和時間範圍,修復大量表以及我可能遇到的 RAM 問題,但我不能使用它,因為TimescaleDB使用了太多儲存空間,所以我需要使用他們的壓縮功能,但是壓縮的超表不允許寫入操作,這意味著為了能夠進行回填(我經常這樣做),我基本上每次都需要解壓縮整個數據庫。

因為InfluxDB這個問題僅僅是因為它們不支持任何numeric/decimal類型,我不能使用double.

隨意提出一些我不知道的其他替代方案,如果有的話,它會很好地適合我的案例。

每個後端(連接所連接的程序)在它接觸過的每個對像上都保留一個數據記憶體。沒有規定過期這個記憶體,所以它確實會隨著它曾經使用過的每個對象而增長。

為什麼你的連接池維護 120 個連接,或者每個 CPU 20 個?這似乎是一個荒謬的數字,尤其是考慮到您已經知道自己有記憶問題。

我發現它接觸到的每個表(有兩個索引)使用大約 6.7kB。我使用了收集的統計數據中的“最大居民”行log_executor_stats=on。這並不適合在生產中使用,但我不知道在這種情況下使用什麼。

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