瞭解Postgres 14新功能:效能和監控改進

banq發表於2021-05-28

即將釋出的Postgres 14版本的第一個Beta版本已於昨天釋出。在本文中,我們將首先了解Beta中的功能,重點是一項主要的效能改進以及三項引起我們注意的監視改進。
在開始之前,我想強調一下作為Postgres一個重要的獨特方面一直令我印象深刻的地方:與大多數其他開源資料庫系統相比,Postgres不是單個公司的專案,而是許多個人一起工作一年又一年的新版本。這包括嘗試試用beta版本並將錯誤報告給Postgres專案的每個人。我們希望這篇文章能激勵您進行自己的測試和基準測試。
現在,我個人對Postgres 14中更好的連線擴充套件感到非常興奮。對於這篇文章,我們執行了一個詳細的基準測試,將Postgres 13.3與14 beta1進行了比較(請注意,連線計數是對數刻度)。
 

Postgres 14中改進的主動和空閒連線擴充套件
對於需要大量資料庫連線的我們來說,Postgres 14帶來了重大改進。Postgres連線模型依賴於程式而不是執行緒。這具有一些重要的好處,但在連線數量較大時也有開銷。透過此新版本,擴充套件活動和空閒連線的效能已顯著提高,對於要求最苛刻的應用程式而言,這將是一項重大改進。
在我們的測試中,我們使用了兩個96個vCore AWS例項(c5.24xlarge),一個例項執行Postgres 13.3,另一個例項執行Postgres 14 beta1。這兩個都使用預設系統設定的Ubuntu 20.04,但是Postgres連線限制已增加到11,000個。
我們使用pgbench測試活動連線的連線比例。首先,我們使用pgbench比例因子200初始化資料庫:

# Postgres 13.3
$ pgbench -i -s 200
...
done in 127.71 s (drop tables 0.02 s, create tables 0.02 s, client-side generate 81.74 s, vacuum 2.63 s, primary keys 43.30 s).
# Postgres 14 beta1
$ pgbench -i -s 200
...
done in 77.33 s (drop tables 0.02 s, create tables 0.02 s, client-side generate 48.19 s, vacuum 2.70 s, primary keys 26.40 s).


我們已經在這裡看到Postgres 14在初始資料載入方面做得更好。
現在,我們啟動具有不同活動連線集的只讀pgbench,以非常活躍的工作負載為例顯示5,000個併發連線:

# Postgres 13.3
$ pgbench -S -c 5000 -j 96 -M prepared -T30
...
tps = 417847.658491 (excluding connections establishing)
# Postgres 14 beta1
$ pgbench -S -c 5000 -j 96 -M prepared -T30
...
tps = 495108.316805 (without initial connection time)


如您所見,具有5000個活動連線的Postgres 14的吞吐量大約高20%。在10,000個活動連線的情況下,與Postgres 13相比,改善了50%;在連線數量減少時,您還可以看到一致的改善。
請注意,當連線數超過CPU數時,通常會看到TPS明顯下降,這很可能是由於CPU排程開銷,而不是Postgres本身的限制。現在,大多數工作負載實際上並沒有這麼多活動的連線,而是有大量的空閒連線。
這項工作的原始作者Andres Freund對單個活動查詢的吞吐量進行了基準測試,同時還執行了10,000個空閒連線。查詢從15,000 TPS增加到將近35,000 TPS-比Postgres 13好2倍。您可以在Andres Freund的原始文章中介紹所有這些改進,以獲取所有詳細資訊。
 

深入研究pg_backend_memory_contexts在記憶體中的使用
您是否曾經好奇過為什麼某個Postgres連線佔用了更多的記憶體?使用新pg_backend_memory_contexts檢視,您可以仔細檢視為給定的Postgres流程分配了什麼。
首先,我們可以計算當前連線總共使用了多少記憶體:

SELECT pg_size_pretty(SUM(used_bytes)) FROM pg_backend_memory_contexts;
pg_size_pretty 
----------------
 939 kB
(1 row)


現在,讓我們進一步深入。當我們按記憶體使用量查詢表中前5個條目時,您會注意到實際上有很多詳細資訊:

SELECT * FROM pg_backend_memory_contexts ORDER BY used_bytes DESC LIMIT 5;

Postgres中的記憶體上下文是一個記憶體區域,用於分配以支援諸如查詢計劃或查詢執行之類的活動。一旦Postgres在上下文中完成工作,就可以釋放整個上下文,從而簡化記憶體處理。透過使用記憶體上下文,Postgres源實際上避免free了大部分手動呼叫(即使它是用C編寫的),而是依賴於記憶體上下文來成組地清理記憶體。
 

使用pg_stat_wal跟蹤WAL活動
在Postgres 13中的WAL監視功能的基礎上,新版本為WAL資訊帶來了伺服器範圍內的新摘要檢視,稱為pg_stat_wal。
您可以使用它來更輕鬆地監視隨時間變化的WAL寫入:

SELECT * FROM pg_stat_wal;

-[ RECORD 1 ]----+------------------------------
wal_records      | 3334645
wal_fpi          | 8480
wal_bytes        | 282414530
wal_buffers_full | 799
wal_write        | 429769
wal_sync         | 428912
wal_write_time   | 0
wal_sync_time    | 0
stats_reset      | 2021-05-21 07:33:22.941452+00



透過這種新檢視,我們可以獲得摘要資訊,例如向WAL中寫入了多少張全頁影像(FPI),從而可以洞悉Postgres何時由於檢查點而生成大量WAL記錄。其次,您可以使用新的wal_buffers_full計數器快速檢視何時將該wal_buffers設定設定得太低,這可能會導致不必要的I / O,可以透過將wal_buffers增大為一個更高的值來防止此情況。
透過啟用可選track_wal_io_timing設定,您還可以獲取有關WAL寫入的I / O影響的更多詳細資訊,該設定為您提供WAL寫入的準確I / O時間,以及WAL檔案同步到磁碟的時間。請注意,此設定可能會有明顯的開銷,因此,除非需要,否則最好將其關閉(預設設定)。
 

使用內建的Postgres query_id監視查詢
TimescaleDB於2021年3月和4月進行的一項最新調查中,pg_stat_statements擴充套件為被調查使用者群與Postgres一起使用的三大擴充套件之一。pg_stat_statements與Postgres捆綁在一起,並且與Postgres 14捆綁在一起,擴充套件的重要功能之一已合併到核心Postgres中:
首先,我們必須啟用新compute_query_id設定,然後重新啟動Postgres:

ALTER SYSTEM SET compute_query_id = 'on';

如果您使用pg_stat_statements 的query Id,則會透過預設compute_query_id設定auto自動計算。
啟用query Id後,我們可以在pg_stat_activitypgbench執行期間進行檢視,並檢視與僅檢視查詢文字相比,這樣做有幫助的原因:

SELECT query, query_id FROM pg_stat_activity WHERE backend_type = 'client backend' LIMIT 5;


UPDATE pgbench_tellers SET tbalance = tbalance + -4416 WHERE tid = 3;  | 885704527939071629
 UPDATE pgbench_tellers SET tbalance = tbalance + -2979 WHERE tid = 10; | 885704527939071629
 UPDATE pgbench_tellers SET tbalance = tbalance + 2560 WHERE tid = 6;   | 885704527939071629
 UPDATE pgbench_tellers SET tbalance = tbalance + -65 WHERE tid = 7;    | 885704527939071629
 UPDATE pgbench_tellers SET tbalance = tbalance + -136 WHERE tid = 9;   | 885704527939071629


從應用程式角度來看,所有這些查詢都是相同的,但是它們的文字略有不同,因此很難在工作負載中找到模式。但是,使用查詢ID,我們可以清楚地識別某些型別的查詢的數量,並更輕鬆地評估效能問題。例如,我們可以按查詢ID分組,以檢視使資料庫繁忙的原因:

SELECT COUNT(*), state, query_id FROM pg_stat_activity WHERE backend_type = 'client backend' GROUP BY 2, 3;


count | state  |       query_id       
-------+--------+----------------------
  40 | active |   885704527939071629
  9 | active |  7660508830961861980
  1 | active | -7810315603562552972
  1 | active | -3907106720789821134


在自己的系統上執行此命令時,您可能會發現query ID與此處顯示的ID不同。這是由於query ID依賴於Postgres查詢的內部表示,而Postgres查詢可能依賴於體系結構,並且還考慮了表的內部ID而不是其名稱。
還可以透過新的%Q選項從log_line_prefix獲得query ID資訊,從而更輕鬆地獲得連結到查詢的auto_explain輸出:

2021-05-21 08:18:02.949 UTC [7176] [user=postgres,db=postgres,app=pgbench,query=885704527939071629] LOG:  duration: 59.827 ms  plan:
    Query Text: UPDATE pgbench_tellers SET tbalance = tbalance + -1902 WHERE tid = 6;
    Update on pgbench_tellers  (cost=4.14..8.16 rows=0 width=0) (actual time=59.825..59.826 rows=0 loops=1)
      ->  Bitmap Heap Scan on pgbench_tellers  (cost=4.14..8.16 rows=1 width=10) (actual time=0.009..0.011 rows=1 loops=1)
            Recheck Cond: (tid = 6)
            Heap Blocks: exact=1
            ->  Bitmap Index Scan on pgbench_tellers_pkey  (cost=0.00..4.14 rows=1 width=0) (actual time=0.003..0.004 rows=1 loops=1)
                  Index Cond: (tid = 6)
想連結auto_explain和pg_stat_statements,並且等不及Postgres 14?
我們建立了自己的開源query fingerprint mechanism,機制是根據其文字唯一地標識查詢。這用於pganalyze中,以將EXPLAIN計劃與查詢進行匹配,並且您也可以在自己的指令碼中使用此版本,與任何Postgres版本一起使用。
 

在Postgres 14版本中還有200多項其他改進!
這些只是新的Postgres版本中許多改進中的一部分。您可以在發行說明中找到更多有關新功能的資訊,例如:

  • 新的預定義角色pg_read_all_data/pg_write_all_data賦予全域性讀或寫訪問許可權
  • 如果客戶端斷開連線,則自動取消長期執行的查詢
  • 現在,當可移動索引條目的數量微不足道時,吸塵會跳過索引吸塵
  • 現在,索引索引資訊已包含在自動真空日誌記錄輸出中
  • 現在可以使用以下非阻塞方式分離分割槽: ALTER TABLE ... DETACH PARTITION ... CONCURRENTLY

還有很多。現在是時候幫助測試了!
官方程式包儲存庫下載beta1 ,或從原始碼進行構建。從現在起的幾個月內,我們所有人都可以為使Postgres 14成為一個穩定的版本做出貢獻。

 

相關文章