Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >A Comprehensive Guide: PostgreSQL Shared Buffers(译)

A Comprehensive Guide: PostgreSQL Shared Buffers(译)

作者头像
数据库架构之美
发布于 2020-12-01 02:32:10
发布于 2020-12-01 02:32:10
84500
代码可运行
举报
运行总次数:0
代码可运行

译者注

MySQL设置innodb_buffer_pool_size = 80%左右的系统内存相比,也就是将操作系统大部分内存分配给Innodb的buffer pool的缓存管理机制不同,Postgresql采用数据库采用实例buffer和操作系统buffer双缓存(effective_cache_size)的工作模式,这一点两者还是有着比较本质上的差异的。

缓存作为数据库的一个核心组件,shared_buffers决定了数据库实例层面的可用内存,而文件系统缓存的大小是effective_cache_size决定的,effective_cache_size不仅是缓存经常访问的数据,它同时帮助优化器确定实际存在多少缓存,指导优化器生成最佳执行计划。 以下几篇文章都比较好地解释了Shared Buffers和操作系统层面文件缓存(os cache)之间的关系,可作为参考

https://www.cybertec-postgresql.com/en/effective_cache_size-what-it-means-in-postgresql/

https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server

https://severalnines.com/database-blog/architecture-and-tuning-memory-postgresql-databases

https://distributedsystemsauthority.com/optimizing-postgresql-shared-buffers/

https://www.enterprisedb.com/edb-docs/d/edb-postgres-advanced-server/user-guides/user-guide/10/EDB_Postgres_Advanced_Server_Guide.1.24.html

https://stackoverflow.com/questions/42478488/resize-shared-buffer-size-in-postgresql-hosted-in-aws-rds

https://devcenter.heroku.com/articles/understanding-postgres-data-caching

查阅到的资料上只是说了一些理论基础,比如shared buffers或者和effective_cache_size设置的过大或者过小理论上存在的问题,但是最终还是没整明白,Postgresql为什么shared buffers(建议值是25%系统内存)和effective_cache_size(建议值是50%系统内存)分配机制的背后原理,也希望有高人指点。

以下为译文。

原文地址:

https://postgreshelp.com/postgresql_shared_buffers/

这篇文章详细回答了以下问题:在PostgreSQL中,你需要给共享缓冲区多少内存?为什么?

额外的福利! !为什么我的RDS postgreSQL共享缓冲区使用系统内存的25%,而Aurora Postgresql的共享缓冲区是75%?答案就在这里。

理解PostgreSQL中的OS Cache vs Shared Buffers

在我们开始之前,首先回答一个问题:BGWriter在PostgreSQL中的作用是什么? 如果你的答案是“它把脏缓冲区写到磁盘”,那就错了。

它实际上将脏缓冲区写入OS缓存,然后进行单独的系统调用,将页面从OS缓存刷新到磁盘。

是不是不太明白吗?可以这么去理解它: 由于它轻量级的特性,PostgreSQL必须高度依赖操作系统缓存,它依赖于操作系统来了解文件系统、磁盘布局以及如何读写数据文件。

下图让您大致了解了数据如何在磁盘和share buffers之间传递。

在这里,每当您发出一个“select * from emp”,您的数据实际上是加载到操作系统缓存(OS cache ),然后到shared buffers。

同样,当您尝试将脏缓冲区刷新到磁盘时,页面实际上是刷新到OS缓存,然后通过一个名为fsync()的单独系统调用刷新到磁盘。

这里,PostgreSQL实际上复制了OS的功能,这意味着OS cache和shared_buffers可以保存相同的页面。

这可能会导致空间浪费,但请记住,OS缓存使用的是简单的LRU,而不是数据库优化的时钟扫描算法(clock sweep algorithm.)。一旦页面在shared_buffers上命中,读取就永远不会到达操作系统缓存,如果有任何副本,则很容易删除它们。

是否可以设置操作系统的fsync()方法刷新脏页到磁盘?

是的,参数在postgresql.conf文件中,bgwriter_flush_after(整数)—默认512 kB 当backend writer写入的数据超过这个数量时,尝试强制操作系统向底层存储发出这些写入操作。

这样做将限制内核页面缓存中的脏数据量,减少在检查点结束时发出fsync或操作系统在后台大量回写数据时暂停的可能性。 它被用作块,即BLCKSZ字节,通常为8kB。

不仅是bgwriter,在PostgreSQL甚至checkpoint进程和用户后端进程也可以将脏缓冲区从共享缓冲区到操作系统缓存。

即使在这里,我们也可以分别使用checkpoint_flush_after和backend_flush_after命令来影响操作系统的fsync()(尽管关于检查指针和后端进程的讨论超出了本文的范围)。

另外请参考:

checkpoint过程综合指南 https://postgreshelp.com/postgresql-checkpoint/

如果给操作系统缓存(OS Cache)分配的值太少了呢?

如上所述,一旦页面被标记为dirty,它就会被刷新到OS缓存中,然后写入磁盘。

在这里,OS可以更自由地根据传入的流量进行I/O。如果操作系统缓存的大小更小,那么它就不能重新排序写操作和优化I/O。这对于编写繁重的工作负载尤其重要。所以操作系统缓存大小也很重要。

译者注:

这里提到的,如果给操作系统分片的缓存值太小,意味着将大部分内存分配给shared buffers,除了上面提到的原因,笔者查阅了很多资料,关于Postgresql实例的OS cache和shared buffers分配比例以及原因都没有一个明确的解释。

比如建议的给shared buffers分配25%的总内存,给effective_cache_size设置50%总内存的具体原理,为什么是这个比例,而不是5:5开或者是7:3开的比例? 在这里有类似问题的解释:

https://www.postgresql-archive.org/Increased-shared-buffer-setting-lower-hit-ratio-td5826899.html

Regarding the unexpected decrease of performance after increasing shared_buffers - that's actually quite common behavior. First, themanagement of shared buffers is not free, and the more pieces you need to manage the more expensive it is. Also, by using larger shared buffers you make that memory unusable for page cache etc. There are also other negative consequences - double buffering, accumulating more changes for a checkpoint etc.

如果给共享缓冲区缓存(shared buffers)的值太少怎么办?

很简单,虽然使用OS缓存进行缓存,但实际的数据库操作是在共享缓冲区中执行的。因此,在共享缓冲区中提供足够的空间是个好主意。

译者注:以下翻译自

https://distributedsystemsauthority.com/optimizing-postgresql-shared-buffers/

PostgreSQL shared_buffers versus operating system cache 如果你习惯了这样的数据库,大部分的系统内存都是给数据库的,而操作系统缓存是通过同步和直接写绕过的,你就不会想用同样的方法来设置PostgreSQL。

但是在Postgresql中这样做适得其反,例如,PostgreSQL的存储在pg_clog目录下提交日志信息。该数据是定期读取和写入的,因此操作系统将负责优化clog的任务。

那么为什么不把所有的内存都给操作系统呢? PostgreSQL共享缓冲区缓存能比操作系统缓存做得更好的主要原因是它保持缓冲区使用计数的方式。

这允许缓冲区获得从0到5的“流行度”分数,分数越高,这些缓冲区离开缓存的可能性就越小。

每当数据库查找要删除的内容以便为其需要的数据腾出更多空间时,就会减少使用计数。使用量的每一次增加都会使该块更难摆脱。这个实现称为时钟扫描算法(clock-sweep algorithm)。典型的操作系统缓存在数据被驱逐之前只会给任何缓冲区一到两次机会。

通常,操作系统会使用某种形式的LRU算法。如果数据库中有经常使用的数据,那么将数据保存在数据库的共享RAM中可能比保存在操作系统的共享RAM中更好。

那么什么是最优值呢?

PostgreSQL建议你将25%的系统内存分配给共享缓冲区,并且你可以根据你的环境随时修改共享缓冲区的值。

如何查看共享缓冲区的内容?

PG缓冲缓存扩展帮助我们实时查看共享缓冲区中的数据。从shared_buffers收集信息并将其放在pg_buffercache中以供查看。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
create extents pg_buffercache;

安装扩展之后,执行下面的查询来检查共享缓冲区的内容。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;

输出的结果类似如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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) > 0postgres-#  GROUP BY c.oid, c.relname
postgres-#  ORDER BY 3 DESCpostgres-#  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)

如何能看到数据实际上是在操作系统级别缓存的?

要检查在操作系统级别缓存的数据,我们需要安装pgfincore包。 这是一个外部模块,提供关于操作系统如何缓存页面的信息。它的级别很低,但却非常强大。

下载pgfincore并执行以下步骤。

As root user:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;

现在执行下面的命令来检查操作系统级别的缓冲区。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;

输出的结果类似如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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表示PostgreSQL缓冲缓存中缓冲了多少数据 pgbuffer_percent表示pg_buffered/total_buffer_size *100 percent_of_relation表示pg_buffered/total_relation_size * 100 os_cache_mb表示在OS中缓存了多少关系 在这里,我们的emp表有8301 MB大小,92%的数据在操作系统缓存中,同时49.3%的数据在共享缓冲区中,也就是大约50%的数据是冗余的。

额外的收获! !

为什么Aurora的PostgreSQL将shared buffers设置为可用内存的75%?

对于RDS DB实例,DB参数组的默认值设置为总内存的25%。但是对于Aurora DB实例,DB参数组的默认值设置为总内存的75%。

这是因为Aurora PostgreSQL消除了双缓冲,并且不使用文件系统缓存。 因此,Aurora PostgreSQL可以通过增加shared_buffers来提高性能。在使用Aurora PostgreSQL时,shared_buffers DB参数的默认值为75%是一个最佳实践。

众所周知,work_mem、maintenance_work_mem和其他本地内存组件都不是shared buffers的一部分,在aurora中,如果你的应用程序需要大量的work_mem或者你的应用程序需要更多的客户端连接,你会遇到set shared_buffers值小于75%的情况。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据库架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
综合指南:postgresql shared buffers
本文主要针对下面问题详述PG的共享内存:PG中需要给共享内存分配多少内存?为什么?
yzsDBA
2021/01/05
1.6K0
综合指南:postgresql shared buffers
PostgreSql 学了还是乱麻,那就捋一捋 DB架构
其实学习的过程中,很容易陷入一个问题,貌似都懂,一问就含糊,今天就自己捋一捋的那团乱麻。
AustinDatabases
2020/05/09
5200
[PostgreSQL] - 存储结构及缓存shared_buffers
包含三个文件, 具体介绍请看PostgreSQL目录结构之base目录,Free Space Map and Visibility Map:
夹胡碰
2022/07/30
2.6K0
[PostgreSQL] - 存储结构及缓存shared_buffers
PG中的WAL:1 buffer cache
数据库管理系统需要操作的数据位于RAM,并会异步刷写到磁盘或其他非易失性存储介质。写被推迟,推迟时间越久IO次数越少,系统操作越快。
yzsDBA
2021/05/17
9270
PG中的WAL:1 buffer cache
PostgreSQL集群篇——常用的运维SQL
本文主要是我日常使用的一些运维SQL和整理于互联网上的SQL,为了方便日常的使用,特把其汇总起来,遇到常用的时将会进行补充该文,欢迎大家在评论区进行提出一些常用的SQL。
cn華少
2021/11/24
1.2K0
Postgresql内部缓存与OS缓存的关系
mysql通常使用odirect使数据绕过OS缓冲区落盘,wal还是使用系统缓冲。这样数据的写盘不会造成系统刷脏抖动。在pgsql中数据是与OS缓冲绑定的,自己没有做字节对齐,也不使用odirect的方式直写设备,社区对数据直写的态度也一直很悲观,原因是之前也做过很多探索,结果都不是很好:
mingjie
2022/05/12
5550
Postgresql内部缓存与OS缓存的关系
[译]PostgreSQL16-新特性-新增IO统计视图:pg_stat_io
获取PG服务产生的所有IO情况历来都是一个挑战。首先,PG将IO行为范围内为写WAL和读写数据目录(也就是数据文件)。真正的挑战是:理解围绕写入的二阶效应:通常数据的写入发生在事务提交后,即异步刷写,这就对理解哪个进程实际写入数据目录(以及何时)带来困难。
yzsDBA
2023/02/26
1K0
[译]PostgreSQL16-新特性-新增IO统计视图:pg_stat_io
进阶数据库系列(二十三):PostgreSQL 性能优化
PostgreSQL数据库优化是多方面的,原则是减少系统的瓶颈,减少资源的占用,增加系统的反应速度。例如:
民工哥
2023/08/22
3.8K0
进阶数据库系列(二十三):PostgreSQL 性能优化
Postgresql存储结构
如果阅读过手册一定听过postgresql cluster的概念,第一次听到这个概念可能都会有一些困惑。cluster在安装数据库时,由initdb工具生成,initdb后产生的pgdata文件夹可以理解为cluster的物理存储结构。数据库启动、停止时pg_ctl -D参数指定的文件夹即cluster文件夹,所以一个PG Server可以运行在一个PG Cluster上。
mingjie
2022/05/12
1.2K0
Postgresql存储结构
PostgreSQL体系架构介绍
PostgreSQL是最像Oracle的开源数据库,我们可以拿Oracle来比较学习它的体系结构,比较容易理解。PostgreSQL的主要结构如下:
用户8006012
2022/07/26
2.3K0
PostgreSQL技术大讲堂 - 第32讲:数据库参数调整
PostgreSQL从小白到专家,是从入门逐渐能力提升的一个系列教程,内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容,希望对热爱PG、学习PG的同学们有帮助,欢迎持续关注CUUG PG技术大讲堂。
用户5892232
2023/11/03
4050
PostgreSQL技术大讲堂 - 第32讲:数据库参数调整
PostgreSQL 数据读取快慢,你有做主的权利
PostgreSQL使用shared_buffers来缓存内存中的块。其思想是减少磁盘I/O并以最有效的方式加速数据库。在正常操作期间,数据库缓存将非常有用,并确保良好的响应时间。但是,如果由于某种原
AustinDatabases
2019/10/23
1.4K0
PostgreSQL  数据读取快慢,你有做主的权利
【赵渝强老师】史上最详细的PostgreSQL体系架构介绍
PostgreSQL是最像Oracle的开源数据库,我们可以拿Oracle来比较学习它的体系结构,比较容易理解。PostgreSQL的主要结构如下:
赵渝强老师
2024/08/11
6800
【赵渝强老师】史上最详细的PostgreSQL体系架构介绍
《Postgresql 内幕探索》读书笔记 - 第一章:集簇、表空间、元组
PostgreSQL天然集群,多个集群可以组成集簇,有点类似军队的连、团、旅这样的组织规则。对于我们日常学习使用的单节点则是单个集簇单个集群,自己就是集群。
阿东
2023/06/27
6230
《Postgresql 内幕探索》读书笔记 - 第一章:集簇、表空间、元组
史上最全PostgreSQL体系结构
墨墨导读:本文主要从日志文件、参数文件、控制文件、数据文件、redo日志(WAL)、后台进程这六个方面来讨论PostgreSQL的结构。
数据和云
2019/07/22
4K0
史上最全PostgreSQL体系结构
PostgreSQL 难搞的事系列 --- vacuum 的由来与PG16的命令的改进 (1)
开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, Sql Server等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共1720人左右 1 + 2 + 3 + 4+5) 另欢迎 OpenGauss GAUSSDB的技术人员加入
AustinDatabases
2023/11/17
3490
PostgreSQL  难搞的事系列 --- vacuum 的由来与PG16的命令的改进 (1)
PostgreSQL 如何对索引进行分析和处理
最近有人私信问POSTGRESQL 怎么比MYSQL的索引大,这个问题升级上我个人觉得从这几点考虑
AustinDatabases
2023/09/06
2620
PostgreSQL 如何对索引进行分析和处理
PostgreSql Postgresql 监控你说了不算,谁说了算 ? (5 整理的一些脚本)
一写就写到了第五期,有点写连续剧的味道,可能会有第六期,我想是,今天的内容并不是某些工具,其实工具也是根据数据库的原理,通过各种方式获得数据。那怎么通过PG中的系统表来获得数据就是这期的重点。
AustinDatabases
2020/07/16
7080
PostgreSql  Postgresql 监控你说了不算,谁说了算 ? (5  整理的一些脚本)
PostgreSQL 扫盲贴 常用的监控分析脚本
我一直有一个错觉,大家的POSTGRESQL的技术都非常了得,在年前实际上对我有几次的感触。
AustinDatabases
2025/03/03
630
PostgreSQL 扫盲贴 常用的监控分析脚本
GreenPlum 7.1.0新特性介绍
GreenPlum 7.0.0于2023-09-28发布,大约半年后,GreenPlum 7.1.0于2024-02-09发布。
AiDBA宝典
2024/02/26
9451
GreenPlum 7.1.0新特性介绍
推荐阅读
相关推荐
综合指南:postgresql shared buffers
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验