訂閱
糾錯
加入自媒體

PG中需要給共享內存分配多少內存?為什么?

2021-03-05 09:32
yzsDBA
關注

綜合指南:postgresql shared buffers

本文主要針對下面問題詳述PG的共享內存:PG中需要給共享內存分配多少內存?為什么?

非常奇怪,為什么我的RDS PG需要使用系統(tǒng)RAM的25%,而Aurora的PG卻需要分配75%?

理解PG中的共享內存及操作系統(tǒng)的緩存

首先提出個問題:PG中的bgwriter進程是干什么的?

如果回答是將臟頁刷到磁盤的,那這就錯了。他僅僅將臟頁刷寫到操作系統(tǒng)的緩存,然后由操作系統(tǒng)調用sync將操作系統(tǒng)緩存刷寫到磁盤。有點迷惑?那么接著我們說道說道。

由于PG輕量的特性,他高度依賴操作系統(tǒng)緩存,通過操作系統(tǒng)感知文件系統(tǒng)、磁盤布局以及讀寫數(shù)據(jù)文件。下圖幫助了解數(shù)據(jù)如何在磁盤和共享緩存之間流動。

因此當發(fā)起“select *from emp”時,數(shù)據(jù)會加載到操作系統(tǒng)緩存然后才到shared buffer。同樣當將臟頁向磁盤刷寫時,也是先到操作系統(tǒng)緩存,然后由操作系統(tǒng)調用fsync()將操作系統(tǒng)緩存中數(shù)據(jù)持久化到磁盤。這樣PG實際上由兩份數(shù)據(jù),看起來有些浪費空間,但是操作系統(tǒng)緩存是一個簡單的LRU而不是數(shù)據(jù)庫優(yōu)化的clock sweep algorithm。一旦在shared_buffers中命中,那么讀就不會下沉到操作系統(tǒng)緩存。如果shared buffer和操作系統(tǒng)緩存有相同頁,操作系統(tǒng)緩存中的頁很快會被驅逐替換。

我能影響操作系統(tǒng)的fsync將臟頁刷回磁盤嗎?

當然,通過postgresql.conf中參數(shù)bgwriter_flush_after,該參數(shù)整型,默認512KB。當后臺寫進程寫了這么多數(shù)據(jù)時,會強制OS發(fā)起sync將cache中數(shù)據(jù)刷到底層存儲。這樣會限制內核頁緩存中的臟數(shù)據(jù)數(shù)量,從而減小checkpoint時間或者后臺大批量寫回數(shù)據(jù)的時間。

不僅僅時bgwriter,即使checkpoint進程和用戶進程也從shared buffer刷寫臟頁到OS cache。可以通過checkpoint_flush_after影響checkpoint進程的fsync,通過backend_flush_after影響后臺進程的fsync。

如果給OS cache很小值會怎么樣?

正如上文所述,一旦頁被標記為臟,他就會刷寫到操作系統(tǒng)緩存。操作系統(tǒng)可以更加自由地根據(jù)傳入的流量進行IO調度。如果OS cache太小,則無法重新對write進行排序從而優(yōu)化IO。這對于寫操作頻繁的工作負載尤為重要,所以操作系統(tǒng)緩存大學也很重要。

如果給shared buffer很小值會怎么樣?

數(shù)據(jù)庫操作都在shared buffer,所以最好為shared buffer分配足夠空間。

建議值多大?

PG推薦系統(tǒng)內存的25%給shared buffer,當然可以根據(jù)環(huán)境進行調整。

如果查看shared buffer中內容?

PG的buffer cache擴展可以幫助實時查看shared buffer中內容。從shared_buffers中采集信息保存到pg_buffercache表中:

create extension pg_buffercache;

安裝好后,執(zhí)行下面查詢查看內容:

SELECT c.relname

, pg_size_pretty(count(*) * 8192) as buffered

, round(100.0 * count(*) / ( SELECT setting FROM pg_settings WHERE name='shared_buffers')::integer,1) AS buffers_percent

, round(100.0 * count(*) * 8192 / pg_relation_size(c.oid),1) AS percent_of_relation

FROM pg_class c

INNER JOIN pg_buffercache b ON b.relfilenode = c.relfilenode

INNER JOIN pg_database d ON (b.reldatabase = d.oid AND d.datname = current_database())

WHERE pg_relation_size(c.oid) > 0

GROUP BY c.oid, c.relname

ORDER BY 3 DESC

LIMIT 10;

輸出:

postgres=# SELECT c.relname  postgres-#   ,  pg_size_pretty(count(*) * 8192) as buffered  postgres-#   , round(100.0 *  count(*) / ( SELECT setting FROM pg_settings WHERE  name='shared_buffers')::integer,1) AS buffers_percent  postgres-#   , round(100.0 *  count(*) * 8192 / pg_relation_size(c.oid),1) AS percent_of_relation  postgres-#  FROM pg_class c  postgres-#  INNER JOIN  pg_buffercache b ON b.relfilenode = c.relfilenode  postgres-#  INNER JOIN  pg_database d ON (b.reldatabase = d.oid AND d.datname = current_database())  postgres-#  WHERE  pg_relation_size(c.oid) > 0  postgres-#  GROUP BY c.oid,  c.relname  postgres-#  ORDER BY 3 DESC  postgres-#  LIMIT 10;            relname          |  buffered  |  buffers_percent | percent_of_relation  ---------------------------+------------+-----------------+---------------------   pg_operator                | 80 kB      |              0.1 |                71.4   pg_depend_reference_index  | 96 kB      |              0.1 |                27.9   pg_am                      | 8192 bytes |              0.0 |                100.0   pg_amproc                  | 24 kB      |              0.0 |                100.0   pg_cast                    | 8192 bytes |              0.0 |                50.0   pg_depend                  | 64 kB      |              0.0 |                14.0   pg_index                  |  32 kB      |              0.0 |                100.0   pg_description            |  40 kB      |              0.0 |                14.3   pg_language                | 8192 bytes |              0.0 |                100.0   pg_amop                    | 40 kB      |              0.0 |                83.3  (10 rows)
如何感知數(shù)據(jù)到達操作系統(tǒng)緩存層?

需要安裝包pgfincore:

As root user:      export PATH=/usr/local/pgsql/bin:$PATH //Set  the path to point pg_config.  tar -xvf pgfincore-v1.1.1.tar.gz   cd pgfincore-1.1.1   make clean   make   make install      Now connect to PG and run below command  postgres=# CREATE EXTENSION pgfincore;

執(zhí)行下面命令:

select c.relname,pg_size_pretty(count(*) * 8192) as pg_buffered,
 round(100.0 * count(*) /
(select setting
from pg_settings
where name='shared_buffers')::integer,1)
as pgbuffer_percent,
round(100.0*count(*)*8192 / pg_table_size(c.oid),1) as percent_of_relation,
( select round( sum(pages_mem) * 4 /1024,0 )
from pgfincore(c.relname::text) )
as os_cache_MB ,
round(100 * (
select sum(pages_mem)*4096
from pgfincore(c.relname::text) )/ pg_table_size(c.oid),1)
as os_cache_percent_of_relation,
pg_size_pretty(pg_table_size(c.oid)) as rel_size
from pg_class c
inner join pg_buffercache b on b.relfilenode=c.relfilenode
inner join pg_database d on (b.reldatabase=d.oid and d.datname=current_database()
and c.relnamespace=(select oid from pg_namespace where nspname='public'))
group by c.oid,c.relname
order by 3 desc limit 30;
輸出:
relname |pg_buffered|pgbuffer_per|per_of_relation|os_cache_mb|os_cache_per_of_relation|rel_size
---------+-----------+------------+---------------+-----------+------------------------+--------
emp | 4091 MB | 99.9 | 49.3 | 7643 | 92.1 | 8301 MB

pg_buffered表示PG buffer cache中有多少數(shù)據(jù),pgbuffer_percent表示pg_buffered/total_buffer_size*100。os_cache_mb表示OS cache中緩存多少。我們的表emp有8301MB數(shù)據(jù),92%數(shù)據(jù)在OS cache,49.3%在shared buffers,大約50%的數(shù)據(jù)是冗余的。

為什么Aurora PG推薦75%的內存給shared buffer?

Aurora不使用文件系統(tǒng)緩存,因此可以提升shared_buffers大小以提升性能。最佳實踐值為75%。Work_mem、maintenance_work_mem和其他本地內存不是shared buffer的一部分。如果應用請求大量客戶端連接,或需要大量work_mem時,需要將這個值調小。


聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權或其他問題,請聯(lián)系舉報。

發(fā)表評論

0條評論,0人參與

請輸入評論內容...

請輸入評論/評論長度6~500個字

您提交的評論過于頻繁,請輸入驗證碼繼續(xù)

暫無評論

暫無評論

人工智能 獵頭職位 更多
掃碼關注公眾號
OFweek人工智能網
獲取更多精彩內容
文章糾錯
x
*文字標題:
*糾錯內容:
聯(lián)系郵箱:
*驗 證 碼:

粵公網安備 44030502002758號