Postgres Storage
存储 # 内存 # 共享内存
本地内存
缓存
内存上下文
缓存空间管理
数据块的缓存,减少磁盘IO,有共享缓存和进程缓存
Cache
数据块之外的缓存,例如系统表
系统表缓存不会缓存整个表,是以block为单位缓存? 虚拟文件描述符
系统中文件有打开的上限,使用VFD可以突破这种限制,本质上是一个LRU缓存
空闲空间定位
快速定位磁盘中的空闲空间以插入数据
进程间通信 使用共享内存或者信号量通信
读取过程 # 从系统表中读取表的元数据信息构造元组信息 尝试从缓存读取数据 使用SMGR从磁盘读取数据到缓存中,SMGR是一个抽象层,用于实现不同存储介质的管理 SMGR和存储介质之间使用VFD来管理文件描述符,以突破系统的FD限制 标记删除,vacuum清理数据 FSM记录空闲空间 磁盘 # 表文件
SMGR
VFD
FSM
select * from pg_relation_filepath(‘idx’);
Page 结构 # 工具汇总说明
create extension pageinspect; get_raw_page(relname text, fork text, blkno int) 返回执行表的page,text指定类型,默认是main,代表普通page,使用fsm或者vm查看其他类型,可以省略 page_header(page bytea) 查看page头,输入是page数组,使用上面的函数的输出作为参数 fsm_page_contents(page bytea) returns text 查看fsm页面结构 SELECT fsm_page_contents(get_raw_page('t1', 'fsm', 0)); === HEAP相关 heap_page_items(page bytea) 查看page的具体信息 heap_tuple_infomask_flags(t_infomask integer, t_infomask2 integer) returns record 查看mask的具体含义,具体的使用方法为 SELECT * FROM heap_page_items(get_raw_page('a', 0)), LATERAL heap_tuple_infomask_flags(t_infomask, t_infomask2) WHERE t_infomask IS NOT NULL OR t_infomask2 IS NOT NULL order by lp desc; 输出为 t_infomask2 | t_infomask | t_hoff | t_bits | t_oid | t_data | raw_flags | combined_flags -------------+------------+--------+----------+-------+------------+--------------------------------------------------------------------------+---------------- 3 | 2305 | 24 | 10000000 | | \x02000000 | {HEAP_HASNULL,HEAP_XMIN_COMMITTED,HEAP_XMAX_INVALID} | {} 8195 | 1281 | 24 | 10000000 | | \x01000000 | {HEAP_HASNULL,HEAP_XMIN_COMMITTED,HEAP_XMAX_COMMITTED,HEAP_KEYS_UPDATED} | {} 主要目的是查看数据的mask的信息 === Btree相关 bt_metap(relname text) 查看btree元数据信息 bt_page_stats(relname text, blkno int) 查看btree page的统计信息 bt_page_items(relname text, blkno int) 或者 bt_page_items(page bytea) returns setof record 查看具体的信息,可以指定index或者直接使用page byte typedef struct PageHeaderData { /* XXX LSN is member of *any* block, not only page-organized ones */ PageXLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog record for last change to this page */ uint16 pd_checksum; /* checksum */ uint16 pd_flags; /* flag bits, see below */ LocationIndex pd_lower; /* offset to start of free space */ LocationIndex pd_upper; /* offset to end of free space */ LocationIndex pd_special; /* offset to start of special space */ uint16 pd_pagesize_version; TransactionId pd_prune_xid; /* oldest prunable XID, or zero if none */ ItemIdData pd_linp[FLEXIBLE_ARRAY_MEMBER]; /* line pointer array */ } PageHeaderData; void PageInit(Page page, Size pageSize, Size specialSize) { PageHeader p = (PageHeader) page; specialSize = MAXALIGN(specialSize); Assert(pageSize == BLCKSZ); Assert(pageSize > specialSize + SizeOfPageHeaderData); /* Make sure all fields of page are zero, as well as unused space */ MemSet(p, 0, pageSize); p->pd_flags = 0; p->pd_lower = SizeOfPageHeaderData; p->pd_upper = pageSize - specialSize; p->pd_special = pageSize - specialSize; PageSetPageSizeAndVersion(page, pageSize, PG_PAGE_LAYOUT_VERSION); /* p->pd_prune_xid = InvalidTransactionId; done by above MemSet */ } 大小为 pageSize,默认为8k,最开始是PageHeader,