PostgreSQL内幕探索—基础知识

news2025/4/16 2:44:33

PostgreSQL内幕探索—基础知识

PostgreSQL(以下简称PG) 起源于 1986 年加州大学伯克利分校的 ‌POSTGRES 项目‌,最初以对象关系模型为核心,支持高级数据类型和复杂查询功能‌。

1996 年更名为 PostgreSQL 并开源,逐步发展为功能全面的企业级关系型数据库系统,支持 SQL 标准并持续扩展特性(如多版本并发控制、地理空间数据支持等)‌

PG基础知识

大致从下面几个方面来了解PG的基础知识

  • 数据集簇
  • 数据库
  • 表和索引
  • 表空间
  • 表文件
  • 元组

数据集簇

数据集簇是一组数据库的集合,由一个PG服务器进行管理,可以简单理解为一个数据库实例。我们通过一张图来了解一个数据集簇的逻辑结构,如下图所示

逻辑结构

图1.1

从图中我们可以知道,一个数据集簇中可以有多个数据库,每个数据库中包含了不同的对象,例如表table、索引index、视图view等。每个对象都有唯一的一个标识,称之为对象标识符oid,PG通过oid来管理各个对象。数据库中对象与oid的映射关系存储在对应的系统目录中,因对象不同有所差异,例如数据库对象存在于pg_database下,而堆表对象存在于pg_class下。如果需要查找对象的oid,可以使用下面的语句

# 查询数据库对象的oid
select datname,oid from pg_database where datname = 'testdb';

# 查询表对象的oid
select relname,oid from pg_class where relname = 't1';
物理结构

上面了解了数据集簇的逻辑结构,我们现在来认识数据集簇的物理结构。数据集簇的物理结构本质上是一个文件目录,包含了很多子目录和文件,通过initdb可以在指定目录$PGDATA下创建一个初始化的数据集簇。下面的重要目录包含了base目录,默认有几个模板数据库,可以直接在目录下直接看到他们的oid。新创建的数据库都会在这个目录下面

数据集簇布局

这里直接摘用文章中的内容来详细展示数据集簇的布局,列出主要的文件和子目录

  • 文件
文件描述
PG_VERSION包含PG主版本号的文件
pg_hba.conf控制PG的客户端认证
pg_ident.conf控制PG的用户名映射
postgresql.conf参数配置文件
postgresql.auto.conf存储使用alter system命令修改的配置参数
postmaster.opts记录上次启动的命令行选项
  • 子目录
子目录描述
base/每个数据库的子目录皆存储在此
global/数据集簇范围的表以及pg_control文件
pg_commit_ts/事务提交时间戳(9.5+)
pg_clog/事务提交状态日志
pg_dynshmem/动态共享内存子系统使用的文件
pg_logical/逻辑解码的状态数据
pg_mulixact/多事务状态数据
pg_notify/LISTEN/NOTIFY数据
pg_repslot/复制槽数据(9.4+)
pg_serial/已提交的可串行化事务数据
pg_snapshots/存储导出的快照信息
pg_stat/统计子系统的永久文件
pg_stat_temp/统计子系统的临时文件
pg_subtrans/子事务状态数据
pg_tblspc/指向表空间的符号连接
pg_twophase/两阶段事务的状态文件
pg_xlog/wal日志文件
数据库布局

在base子目录下有对应的oid目录,例如testdb的oid为16384,那么目录为base/16384

表和索引文件布局

每个小于1GB的表或者索引都在相应的数据库目录下存在对应的文件。数据库内部,表和索引是用oid进行管理的,但是在文件上有所差异,文件中使用的是refilenode,这个refilenode一般和oid相同,但是如果表发生了truncate、reindex、cluster等命令被改变,那么这个refilenode就会发生改变。
使用内置函数pg_relation_filepath可以轻松获取到表或索引对象的文件路径,当表或索引对象的数据超过了那么1GB之后,那么PG会创建一个refilenode.1的新文件,如果新文件再次被用满,生成refilenode.2文件,依此类推
在初始化PG时,可以通过--with-segsize来指定表和索引文件的最大文件大小。

_fsm文件和_vm文件

每个表都有相关联的_fsm(空闲空间映射)文件和_vm(可见性映射)文件,分别存储了表文件上每个页面的空闲空间信息和可见性信息。索引只有_fsm文件

内部相关概念

在数据库内部,这些文件被称为相应的分支。一般有四种分支

  • 0 数据文件本体
  • 1 fsm保存空闲空间信息
  • 2 vm保存可见性信息
  • 3 不常见的特殊分支,表示不被日志记录的表和索引
表空间布局

表空间是在基础目录下附加的目录,在建表时指定表空间,那么会将此表的文件生成到该表空间的目录下,该目录下还会创建一个PG_主版本号_目录版本号的目录。通过pg_tblspc子目录进行关联

堆表文件内部布局

数据文件(堆表,索引,也包括vm和fsm文件)内部被划分为固定长度的页,或者叫区块,大小默认为8KB,可以在PG初始化的时候进行调整。每个文件中的页从0开始编号,称之为区块号。如果当前页被填满,那么在末尾追加一个新页来扩展文件大小。
堆表文件的布局如下图
在这里插入图片描述

下面来详细解释下表文件一个页(区块)中的三种数据类型

  1. 堆元组tuple:这里的tuple可以理解为行,存储的就是数据本身,从页面底部开始堆叠
  2. 行指针:保存者指向堆元组的指针,每个行指针占4B,形成一个简单的数组,扮演了元组索引的角色。每个索引项从1开始编号,这个编号称为偏移量。每次有新元组插入时,同时也会插入行指针,并指向新元组。
  3. 头部数据header:header中包含了很多重要的信息,下面一一列出
    • pd_lsn 记录本页面最近一次变更写入xlog记录的lsn号,和wal机制相关
    • pd_checksum 记录本页面的校验和值
    • pd_lower、pd_upper pd_lower指向行指针的末尾,pd_upper指向最新元组的起始位置,可以使用pd_upper-pd_lower得到当前页大致的剩余可用空间
    • pd_special 在索引页中会用到,在堆表页指向页尾。在索引中指向特殊区域的起始位置,特殊区域是仅由索引使用的特殊数据区域,例如btree,空间索引等
    • pd_prune_xid 本页面中可以修剪的最老元组中的xid
      为了标识表中的元组,数据库内部会使用元组标识符tid来管理。tid由一对值组成,分别是元组所在区块号和行指针数组的偏移量。
      此外,大小如果超过了2KB(1/4)的堆元组会使用一种TOAST的方法来存储和管理

读写元组的方式

下面详细介绍下读写元组的流程,假设目前有一张表,这张表只有一个数据页,且页中只有一个tuple。

写元组

根据列子的情况,我们画出写入元组前后的对比
在这里插入图片描述

我们大致描述一下整体的步骤

  1. 从页面底部插入一条tuple,放在tuple1之后,将pd_upper的指针指向tuple2的起始位置
  2. 在行指针1后面生成一个行指针,偏移量为2,行指针2指向tuple2,pd_lower指向行指针2的末尾
  3. pd_lsn,pg_checksum,pg_flag也被修改为合适的值,后面详细展开说。
读元组

我们这里介绍两种常见的读取方式

  • 顺序扫描:通过扫描每一页的行指针,依次读取所有页面的所有元组。
  • btree索引扫描:索引文件中包含了索引元组,索引元组由一对值组成,key为索引列的值,value为目标元组的tid。这样可以直接通过索引读取到目标元组,避免不必要的页面扫描。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WPS复制粘贴错误 ,文件未找到 mathpage.wll

文章目录 1.错误提示图片2.解决方案1.找到MathType.wll文件和MathType Commands 2016.dotm文件并复制2.找到wps安装地址并拷贝上述两个文件到指定目录 3.重启WPS 1.错误提示图片 2.解决方案 1.找到MathType.wll文件和MathType Commands 2016.dotm文件并复制 MathType.wll地址如…

驱动开发硬核特训 · Day 6 : 深入解析设备模型的数据流与匹配机制 —— 以 i.MX8M 与树莓派为例的实战对比

🔍 B站相应的视屏教程: 📌 内核:博文视频 - 从静态绑定驱动模型到现代设备模型 主题:深入解析设备模型的数据流与匹配机制 —— 以 i.MX8M 与树莓派为例的实战对比 在上一节中,我们从驱动框架的历史演进出…

【UE5 C++课程系列笔记】35——HTTP基础——HTTP客户端异步请求API接口并解析响应的JSON

目录 前言 步骤 一、 搭建异步蓝图节点框架 二、异步蓝图节点嵌入到引擎的执行流程 三、获取本地时间并异步返回 四、获取网络时间并异步返回 五、源码 前言 本文以请求网络/本地时间API为例,介绍如何实现HTTP异步请求。 步骤 一、 搭建异步蓝图节点框架 …

手机静态ip地址怎么获取?方法与解析‌

而在某些特定情境下,我们可能需要为手机设置一个静态IP地址。本文将详细介绍手机静态IP地址详解及获取方法 一、什么是静态IP地址? 静态IP:由用户手动设置的固定IP地址,不会因网络重启或设备重连而改变。 动态IP:由路…

Python 基础语法汇总

Python 语法 │ ├── 基本结构 │ ├── 语句(Statements) │ │ ├── 表达式语句(如赋值、算术运算) │ │ ├── 控制流语句(if, for, while) │ │ ├── 定义语句(def…

Linux上位机开发实践(OpenCV算法硬件加速)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 图像处理里面,opencv基本是一个标准模块。但是由于图像处理的特点,如果所有的算法都是cpu来做的话,效率会很低。…

Spring Boot MongoDB自定义连接池配置

手打不易,如果转摘,请注明出处! 注明原文:http://zhangxiaofan.blog.csdn.net/article/details/144341407 一、引言 在 Spring Boot 应用中使用 MongoDB 时,合理配置连接池可以显著提升数据库访问的性能和稳定性。默…

游戏引擎学习第223天

回顾 今天我们正在进行过场动画序列的制作,因此我想深入探讨这个部分。昨天,我们暂时停止了过场动画的制作,距离最终结局还有一些内容没有完成。今天的目标是继续完成这些内容。 我们已经制作了一个过场动画的系列,并把它们集中…

DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar),日历_基础功能示例(CalendarView01_01)

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar),日历_基础功能示例(CalendarView01_01)📚…

LabVIEW配电器自动测试系统

随着航天技术的迅猛发展,航天器供配电系统的结构越来越复杂,对配电器的功能完整性、稳定性和可靠性提出了更高要求。传统人工测试方式难以满足高效率、高精度、可重复的测试需求。本项目开发了一套基于LabVIEW平台的宇航配电器自动测试系统,融…

PhotoShop学习09

1.弯曲钢笔工具 PhotoShop提供了弯曲钢笔工具可以直观地创建路径,只需要对分段推拉就能够进行修改。弯曲港币工具位于工具面板中的钢笔工具里,它的快捷键为P。 在使用前,可以把填充和描边选为空颜色,并打开路径选项,勾…

【C++】哈希unordered_map和set的使用以及哈希表,哈希桶的概念以及底层实现

📚 博主的专栏 🐧 Linux | 🖥️ C | 📊 数据结构 | 💡C 算法 | 🌐 C 语言 本文章完整代码在下篇文章开头给出 上篇文章:map和set使用红黑树封装的底层实现 下篇文章:封装…

设计模式——建造者模式(生成器模式)总结

当我们需要创建一个非常复杂的对象时,可以使用建造者模式,分步骤建造一个对象,最后将完整的对象返回给客户端。 比如,我们要生成一个房子对象,建造一个房子,需要打地基、盖围墙、盖地板、安装门、安装窗户…

使用Python爬虫的2大原因和6大常用库

爬虫其实就是请求http、解析网页、存储数据的过程,并非高深的技术,但凡是编程语言都能做,连Excel VBA都可以实现爬虫,但Python爬虫的使用频率最高、场景最广。 这可不仅仅是因为Python有众多爬虫和数据处理库,还有一个…

Java 架构设计:从单体架构到微服务的转型之路

Java 架构设计:从单体架构到微服务的转型之路 在现代软件开发中,架构设计的选择对系统的可扩展性、可维护性和性能有着深远的影响。随着业务需求的日益复杂和用户规模的不断增长,传统的单体架构逐渐暴露出其局限性,而微服务架构作…

C# 混淆代码工具--ConfuserEx功能与使用指南

目录 1 前言1.1 可能带来的问题 2 ConfuserEx2.1 简介2.2 功能特点2.3 基本使用方法2.4 集成到MSBuild2.5 深入设置2.5.1 保护机制2.5.1.1 ConfuserEx Protection 2.5.2 精细的代码保护主要特性1. decl-type(string)2.full-name(string)3. is-public()4. match(string)5. match…

使用PyTorch实现目标检测边界框转换与可视化

一、引言 在目标检测任务中,边界框(Bounding Box)的坐标表示与转换是核心基础操作。本文将演示如何: 实现边界框的两种表示形式(角点坐标 vs 中心坐标)之间的转换 使用Matplotlib在图像上可视化边界框 验…

nlp面试重点

深度学习基本原理:梯度下降公式,将损失函数越来越小,最终预测值和实际值误差比较小。 交叉熵:-p(x)logq(x),p(x)是one-hot形式。如果不使用softmax计算交叉熵,是不行的。损失函数可能会非常大,…

欢乐力扣:反转链表二

文章目录 1、题目描述2、思路 1、题目描述 反转链表二。  给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 2、思路 参考官方题解&#xff0c;基本思路…

14-大模型微调和训练之-Hugging Face 模型微调训练(基于 BERT 的中文评价情感分析(二分类))

1. datasets 库核心方法 1.1. 列出数据集 使用 datasets 库&#xff0c;你可以轻松列出所有 Hugging Face 平台上的数据集&#xff1a; from datasets import list_datasets # 列出所有数据集 all_datasets list_datasets() print(all_datasets)1.2. 加载数据集 你可以通过…