[PostgreSQL] - 存储结构及缓存shared_buffers

一、数据存储

1、物理存储位置

-- 查询表所在磁盘的位置
select pg_relation_filepath('表名')
-- out
base/16393/24804

包含三个文件, 具体介绍请看PostgreSQL目录结构之base目录Free Space Map and Visibility Map:

24804代表表的OID(object id)

  • 24804 - 数据和索引文件(超过1G每1G划分一段, 命名*.1, *.2)
  • 24804_fsm(free space map): 空闲空间映射,主要用来保持对关系中可用空间的跟踪。
  • 24804_vm(visibility map): 可见性映射, 每一个堆关系都有一个可见性映射(VM)用来跟踪哪些页面 只包含已知对所有活动事务可见的元组,它也跟踪哪些页面只包含 未被冻结的元组。

注意: 因为一个页是8K,如果一个表的列中可能存储相当大的项,那么该表就会有个与之相关联的TOAST表, 它用于存储无法保留在在表行中的域值的线外存储。 参考68.2. TOAST

2、物理存储结构

每个表每8K分一页,行数据存在页中

-- 查询表页数、行数
SELECT relpages as 页个数, reltuples as 行个数 FROM pg_class WHERE relname = '表名'

-- 查询占空间大小(排名前20) - 待考证
SELECT table_schema || '.' || table_name                                                         AS table_full_name,
       pg_size_pretty(pg_total_relation_size('"' || table_schema || '"."' || table_name || '"')) AS size
FROM information_schema.tables
ORDER BY pg_total_relation_size('"' || table_schema || '"."' || table_name || '"') DESC
limit 20;

表中的一个页面包含如下描述的三种数据:

  1. heap tuple(s) ——堆元组本身就是一个记录数据。它们从页面底部开始按顺序堆叠。
  2. line pointer(s) – 一个行指针有 4 个字节长,并保存一个指向每个堆元组的指针。它也称为项目指针
    行指针组成一个简单的数组,起到元组索引的作用。每个索引从 1 开始按顺序编号,称为偏移编号。当一个新的元组被添加到页面时,一个新的行指针也被推到数组上以指向新的。
  3. 标头数据——由结构PageHeaderData定义的标头数据分配在页面的开头。它长 24 字节,包含有关页面的一般信息。结构的主要变量如下所述。
  • pd_lsn——这个变量存储了本页最后一次更改写入的 XLOG 记录的 LSN。它是一个 8 字节的无符号整数,与 WAL(Write-Ahead Logging)机制有关。
  • pd_checksum – 此变量存储此页面的校验和值。
  • pd_lower, pd_upper – pd_lower 指向行尾指针,pd_upper 指向最新堆元组的开头。
  • pd_special – 此变量用于索引。在表中的页面中,它指向页面的末尾。(在索引内的页面中,它指向特殊空间的开头,即只有索引持有的数据区域,根据索引类型的种类,如B-tree、GiST、GiN等包含特定的数据。)

二、检索

1、数据扫描方式

左侧为顺序扫描,右侧为b-tree索引扫描

b-tree扫描细节

三、缓存cache

参考: 深入理解Postgres中的cache

1、概述

我们知道,大多数OLTP工作负载是随机的I/O,但是从磁盘获取非常缓慢。为了克服这个问题,和其它现有的数据库系统差不多,Postgres也把数据缓存到RAM(也就是我们说的内存)以提高性能。


2、缓存 shared_buffers

shared_buffers所代表的内存区域可以看成是一个以8KB的block为单位的数组,即最小的分配单位是8KB。这正好是一个page的大小,每个page以page内部的元数据(Page Header)互相区分。

这样,当Postgres想要从disk获取(主要是table和index)数据(page)时,他会(根据page的元数据)先搜索shared_buffers,确认该page是否在shared_buffers中,如果存在,则直接命中,返回缓存的数据以避免I/O。
如果不存在,Postgres才会通过I/O访问disk获取数据(显然要比从shared_buffers中获取慢得多)。

3、缓存淘汰

以页为单位,cache满的时候,会淘汰不常用的页。淘汰后的数据则进行刷盘,但是一般数据都是通过WAL+Checkpointer保证修改的数据刷盘,而不用等到cache满了才进行刷盘。

4、如何观察是否走cache

使用explain时,Shared read表示来自disk,Shared hit则是已经在cache中

图形化分析也有展示


image.png

5、查看缓存情况

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 buffer_percent,
     round(100.0 * count(*) * 8192 / pg_table_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;

6、缓存置为失效

参考: PostgreSQL查询shared buffer使用情况和清理方式

7、缓存刷盘策略

写操作先写WAL日志,写成功之后再写内存数据,之后Checkpointer进行数据刷盘,缓存数据即为最新数据。


四、对我们优化查询有什么借鉴

1、重点表数据常驻缓存

参考: PostgreSQL-缓存利器
重点数据、实时性要求高的数据手动加载至数据库缓存中,减少重点数据的内存淘汰,不稳定IO。同时要考虑刷盘问题,宕机容灾问题。
这同时会牺牲其余不重点功能的性能,需要实际去压测。

2、计算系统和查询系统主从分离

计算服务-写主
报表读服务-读从

  • 优势:
    1、主从服务因为行为不一样,所以热点数据不一样,隔离开来保证各自缓存命中率更高。
  • 其他影响:
    1、主从即便有延迟,也是跑数数据没有及时生成,只要延迟不高,影响则不大。
    2、系统变复杂,易维护性降低。

3、单测、压测时要排除数据库缓存干扰

排除干扰,或者带上缓存综合去考虑优化方案。

五、其他优化方向

1、PREPARE预加载,PostgreSQL手册-prepare
2、PostgreSQL 列存索引 - 新方式 - 列存
3、PostgreSQL 列存, 混合存储, 列存索引, 向量化存储, 混合索引 - OLTP OLAP OLXP HTAP 混合负载应用
4、介绍PostgreSQL CTE(common table expressions) - with as 简化

参考

1、深入理解Postgres中的cache
2、PostgreSQL物理存储简介
3、PostgreSQL Internals Through Pictures
4、The Internals of PostgreSQL

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容