PostgreSQL-shared_buffers(双缓存)

关于shared_buffers
这是一篇2018年写的,可以结合shared read一起看

什么是shred_buffer,我们为什么需要shared_buffers?
1.在数据库系统中,我们主要关注磁盘io,大多数oltp工作负载都是随机io,因此从磁盘获取非常慢。

2.为了解决这个问题,postgres将数据缓存在RAM中,以此来提高性能,即使ssd的情况下RAM也要快很多。

3.shared_buffers是一个8KB的数组,postgres在从磁盘中查询数据前,会先查找shared_buffers的页,如果命中,就直接返回,避免从磁盘查询。

shared_buffers存储什么?
1.表数据

2.索引,索引也存储在8K块中。

3.执行计划,存储基于会话的执行计划,会话结束,缓存的计划也就被丢弃。

什么时候加载shared_buffers?
1.在访问数据时,数据会先加载到os缓存,然后再加载到shared_buffers,这个加载过程可能是一些查询,也可以使用pg_prewarm预热缓存。

2.当然也可能同时存在os和shared_buffers两份一样的缓存(双缓存)。

3.查找到的时候会先在shared_buffers查找是否有缓存,如果没有再到os缓存查找,最后再从磁盘获取。

4.os缓存使用简单的LRU(移除最近最久未使用的缓存),而数据库采用的优化的时钟扫描,即缓存使用频率高的会被保存,低的被移除。

shared_buffers设置的合理范围
1.windows服务器有用范围是64MB到512MB,默认128MB

2.linux服务器建议设置为25%,亚马逊服务器设置为75%(避免双缓存,数据会存储在os和shared_buffers两份)

os缓存的重要性
数据写入时,从内存到磁盘,这个页面就会被标记为脏页,一旦被标记为脏页,它就会被刷新到os缓存,然后写入磁盘。所以如果os高速缓存大小较小,则它不能重新排序写入并优化io,这对于繁重的写入来说非常致命,因此os的缓存大小也非常重要。给予shared_buffers太大或太小都会损害性能。

查看shared_buffers,os缓存
这里需要使用到两个插件,pg_bufferscache系统已经自带可以直接创建扩展,pgfincore需要安装详细的步骤

查询 shared_buffers 占比和缓存情况:

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,
round(sum(pages_mem) * 4 / 1024, 0) AS os_cache_MB,
round(100 * sum(pages_mem) * 4096 / 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_percent | percent_of_relation | os_cache_mb | os_cache_percent_of_relation | rel_size
-------------------±------------±-----------------±--------------------±------------±-----------------------------±---------
pgbench_accounts | 471 MB | 1.9 | 7.3 | 495 | 7.7 | 6416 MB
pgbench_accounts_pkey | 139 MB | 0.6 | 13.0 | 274 | 25.6 | 1071 MB
pgbench_history | 2704 kB | 0.0 | 86.9 | 3 | 99.2 | 3112 kB
pgbench_branches_pkey | 56 kB | 0.0 | 100.0 | 0 | 100.0 | 56 kB
pgbench_tellers_pkey | 240 kB | 0.0 | 100.0 | 0 | 100.0 | 240 kB
pgbench_branches | 2968 kB | 0.0 | 70.7 | 4 | 99.2 | 4200 kB
pgbench_tellers | 608 kB | 0.0 | 100.0 | 1 | 94.7 | 608 kB
预热缓存和查看结果:
– 表缓存预热
SELECT pg_prewarm(‘pgbench_accounts’, ‘buffer’, ‘main’);

– 索引预热
SELECT pg_prewarm(‘pgbench_accounts_pkey’, ‘buffer’, ‘main’);

– 预热后查看缓存
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,
round(sum(pages_mem) * 4 / 1024, 0) AS os_cache_MB,
round(100 * sum(pages_mem) * 4096 / 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_percent | percent_of_relation | os_cache_mb | os_cache_percent_of_relation | rel_size
-------------------±------------±-----------------±--------------------±------------±-----------------------------±---------
pgbench_accounts | 6414 MB | 26.1 | 100.0 | 6414 | 100.0 | 6416 MB
pgbench_accounts_pkey | 139 MB | 0.6 | 13.0 | 274 | 25.6 | 1071 MB
pgbench_history | 2704 kB | 0.0 | 86.9 | 3 | 99.2 | 3112 kB
pgbench_branches_pkey | 56 kB | 0.0 | 100.0 | 0 | 100.0 | 56 kB
pgbench_tellers_pkey | 240 kB | 0.0 | 100.0 | 0 | 100.0 | 240 kB
pgbench_branches | 2968 kB | 0.0 | 70.7 | 4 | 99.2 | 4200 kB
pgbench_tellers | 608 kB | 0.0 | 100.0 | 1 | 94.7 | 608 kB

如何设定shared_buffers?
使用pg_buffercache可查看缓存使用情况,以及命中次数和脏块

缓存命中数
– 缓存命中数
SELECT usagecount, count(*), isdirty
FROM pg_buffercache
GROUP BY isdirty, usagecount
ORDER BY isdirty, usagecount;
结果:

usagecount | count | isdirty
-----------±--------±--------
1 | 6651 | f
2 | 762250 | f
3 | 54684 | f
4 | 12630 | f
5 | 3940 | f
| 2305573 |
数据在缓存中的占比:

– 数据在缓存中占比
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())
GROUP BY
c.oid, c.relname
ORDER BY
3 DESC
LIMIT 10;
结果:

relname | buffered | buffers_percent | percent_of_relation
-----------------------±----------±----------------±--------------------
pgbench_accounts | 6414 MB | 26.1 | 100.0
pgbench_accounts_pkey | 1071 MB | 4.4 | 100.0
pg_amop | 56 kB | 0.0 | 87.5
pg_cast | 16 kB | 0.0 | 100.0
pg_constraint | 8192 bytes| 0.0 | 100.0
pg_index | 32 kB | 0.0 | 100.0
pg_opclass | 16 kB | 0.0 | 66.7
pg_namespace | 8192 bytes| 0.0 | 100.0
pg_operator | 120 kB | 0.0 | 100.0
pg_amproc | 40 kB | 0.0 | 100.0
从结果看出,缓存中存储了完整的表和索引,占总缓存的30%,占比较低,缓存剩余很多。

1.如果大量的usagecount都是4或者5,那表明shared_buffers不够,应该扩大shared_buffers;

2.如果大量的usagecount都是0或者1,那表明shared_buffers过大,应该减小shared_buffers;

每当共享内存中使用一个块时,它就会增加一次时钟扫描算法,范围从1-5。4和5标识极高的使用数据块,高使用可能会保留在shared_buffers中(有空间),如果需要更高使用率的空间,则低使用率的块将被移除,一般简单的插入或者更新会将使用次数设置为1。

缓存占比低。可以确定的是如果我们的数据集非常小,那么设置较大的shared_buffers,没什么区别。

pgbench性能测试(shared_buffers 128MB,4GB,8GB,24GB)
PostgreSQL默认测试脚本,含UPDATE、INSERT还有SELECT等操作。通过修改shared_buffers大小来测试tps。

数据库版本:PostgreSQL 10.4 (ArteryBase 5.0.0, Thunisoft)

操作系统配置:CentOS Linux release 7 ,32GB内存,8 cpu

测试参数:初始化5000w数据:pgbench -i -s 500 -h localhost -U sa -d pgbench

测试方法:pgbench -c 500 -t 20 -n -r pgbench 模拟500客户端,每个客户端20个事务,每种配置参数执行三次,记录tps值。

数据库物理大小:数据库总大小7503 MB,其中表总大小pgbench_accounts:7487 MB,索引pgbench_accounts_pkey :1071 MB

测试脚本:

– 事务延迟(毫秒)
\set aid random(1, 100000 * :scale)
\set bid random(1, 1 * :scale)
\set tid random(1, 10 * :scale)
\set delta random(-5000, 5000)

– 执行事务
BEGIN;
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
END;
结果:

statement latencies in milliseconds:
0.002 \set aid random(1, 100000 * :scale)
0.001 \set bid random(1, 1 * :scale)
0.001 \set tid random(1, 10 * :scale)
0.001 \set delta random(-5000, 5000)
9.478 BEGIN;
14.575 UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
6.758 SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
130.573 UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
786.933 UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
5.355 INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
1242.835 END;

未预热缓存测试结果:

– TPS测试结果
SELECT
‘shared_buffers=128MB(默认)’ AS config,
249 AS first_time,
126 AS second_time,
145 AS third_time,
173 AS average_tps

UNION

SELECT
‘shared_buffers=4GB’,
357,
357,
373,
362

UNION

SELECT
‘shared_buffers=8GB’,
362,
363,
415,
380

UNION

SELECT
‘shared_buffers=24GB’,
378,
368,
397,
381;

shared_buffers设置为8GB(25%)和设置为24GB(75%)差别不大。

预热缓存测试结果:

– TPS测试结果
SELECT
‘shared_buffers=128MB(默认)’ AS config,
211 AS first_time,
194 AS second_time,
207 AS third_time,
204 AS average_tps

UNION

SELECT
‘shared_buffers=4GB’,
1225,
1288,
1321,
1278

UNION

SELECT
‘shared_buffers=8GB’,
1176,
1291,
1144,
1203

UNION

SELECT
‘shared_buffers=24GB’,
1285,
1250,
1309,
1281;
当shared_buffers=4GB时,数据6GB不能完全装下,所以优先预热索引,将索引加载到缓存,然后再加载数据。可以看到最终shared_buffers=4GB的tps和8GB,24GB表现差别不大。

内存结构

1.本地内存:work_mem,maintenance_work_mem,temp_buffer,进程分配

2.共享内存:shared_buffers,wal buffers,commitLog buffer

本地内存*max_connections+共享内存+服务器使用内存<=总内存

小结
1.大多数情况设置shared_buffers为内存的25%,当然为了最优可以根据命中,以及缓存占比调整。

2.设置shared_buffers为75%和25%相差不大,也和数据量一共只有7G+有关系。但是os系统缓存同样重要,而设置为75%,可能会超过总内存。

3.设置所有的缓存需要注意不要超过总内存大小。

4.在预热数据的过程中可以考虑先做索引的预热,因为要做索引的情况加载索引会比较慢。

#PG数据库工程师的摇篮#PostgreSQL考试#PostgreSQL培训

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/236843.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zabbix配置snmp trap--使用snmptrapd和Bash接收器(图文教程)

1.前言 我的zabbix的版本是5.0版本&#xff0c;5.0的官方文档没有使用bash接收器的示例&#xff0c;6.0的官方文档有使用bash接收器的示例&#xff0c;但是&#xff0c;下载文件的链接失效&#xff1f;&#xff01; 这里讲解zabbix-server端配置和zabbix web端配置 2.zabbix-…

基于YOLOv8深度学习的安全帽目标检测系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

C51--DHT11数据读取

DHT11传输0的时序分析&#xff1a; DHT11传输1的时序分析&#xff1a; 用while(dht)卡点&#xff0c;当不满足while时&#xff0c;信号拉低&#xff1b; 用while(&#xff01;dht)卡点&#xff0c;当不满足while时&#xff0c;信号拉高。 传输0和1时有效数据都是高电平&…

【数据结构】—AVL树(C++实现)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 &#x1f49c;本文前置知识&#xff1a; 搜索二叉树 ♈️今日夜电波&#xff1a;Letter Song—ヲタみん 1:36━━━━━━️&#x1f49f;──────── 5:35 …

C 语言超全练习题(一): 初识C语言

文章目录 一、问答题1.1 C语言开发过程是怎样的&#xff1f;1.2 C语言的应用领域有哪些&#xff1f; 二、上机题2.1 第一个C语言程序2.2 一个完整的C语言程序2.3 输出名言2.4 计算出正方形的周长 一、问答题 1.1 C语言开发过程是怎样的&#xff1f; 问题描述&#xff1a;C语言…

10kv配电室无人值守系统

10kv配电室无人值守系统是一种自动化控制系统&#xff0c;依托电易云-智慧电力物联网可以实现对配电室的监测、控制、保护和故障诊断等功能&#xff0c;从而实现配电室的无人值守。该系统主要由控制器、传感器、执行机构、通信模块等组成&#xff0c;可以实现对电力设备的自动化…

【Windows】内网穿透实现hMailServer远程发送邮件

目录 前言1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 前言 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpolar内网…

mongoDB非关系型数据库学习记录

一、简介 1.1Mongodb是什么 MongoDB是一个基于分布式文件存储的数据库,官方地址https://www.mongodb.com/ 1.2数据库是什么 数据库(DataBase)是按照数据结构来组织、存储和管理数据的应用程序 1.3数据库的作用 数据库的主要作用就是管理数据,对数据进行增©、删(d)、…

会员管理系统的意义何在?

在当今的商业环境中&#xff0c;会员管理系统已经成为企业运营的重要组成部分。会员管理系统的意义在于不仅能够帮助企业提高效率&#xff0c;提升用户体验&#xff0c;进行数据分析&#xff0c;营销推广&#xff0c;还能够帮助企业增加收入。下面&#xff0c;我们将详细探讨会…

【HTTP协议】简述HTTP协议的概念和特点

&#x1f38a;专栏【网络编程】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f970;欢迎并且感谢大家指出小吉的问题 文章目录 &#x1f33a;概念&#x1f33a;特点&#x1f384;请求协议&#x1f384;响应协议…

Everything结合内网穿透搭建在线资料库并实现随时随地远程访问

Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问 文章目录 Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问前言1.软件安装完成后&#xff0c;打开Everything2.登录cpolar官网 设置空白数据隧道3.将空白数据隧道与本地Everything软件结合起来总结 前…

为何要隐藏IP地址?代理ip在网络安全和隐私保护中的作用是什么?

目录 前言 一、为何要隐藏IP地址&#xff1f; 1. 保护隐私。 2. 防止网络攻击。 3. 避免限制和审查。 二、网络上哪些行为需要隐藏IP和更换IP&#xff1f; 1. 下载种子文件。 2. 访问受限网站。 3. 保护网络隐私。 4. 避免被封禁。 三、代理IP在网络安全和隐私保护中…