当前位置: 首页 > news >正文

PostgreSQL 为什么不选择 B+ 树索引? - Lafite

我们知道,MySQL 的索引设计使用了 B+Tree,而 PostgreSQL 使用了 B-Tree,
那 PostgreSQL 为什么不使用 B+Tree 做索引结构呢?今天就来聊一聊这个话题。

B+Tree 和 B-Tree

B+TreeB+Tree

主键索引的叶子节点存储数据,非叶子节点(索引节点)则存储 key 和指针。这样存储的优势是可以在索引节点通过二分查找快速找到数据所在页,时间复杂度为 O(logmN),其中 N 是总的节点数量,m 是每个节点的子节点个数。找到数据页后再去数据页中找数据就很容易了。

image

B+Tree的第二个特点是叶子节点用双向链表串联起来,这样范围查询优势很大,时间复杂度为O(logmN+K)。

B-Tree跟

B+Tree不一样的是,B-tree所有节点都可以存储数据,包括根节点,内部节点,叶子节点。

image

随机查询:因为 B-Tree在非叶子节点也能存储数据,B-Tree可能在非叶子节点提前终止查询,查询路径更短。

范围查询:B-Tree查询一个数据范围时需要中序遍历多个层级,这一点效率不如 B+Tree。

PostgreSQL 索引

索引介绍

PostgreSQL 索引对 B-Tree 进行了改造。改造后的索引结构如下图:

image

上图的索引结构中最顶层是元数据页,存储索引根节点页相关信息。内部节点位于根节点下面,只包含键值和指向子页面的指针。叶子页位于最下面一层,存储所有指向实际表数据行(TIDs)的指针。

什么是 TID?PostgreSQL 采用堆表存储,数据独立于索引存储在一个无序的结构中。数据行插入时,数据库会找到一个空闲的空间来存放它,并记录一个唯一的物理地址,称为 TID,由页号和行指针组成。

因为 B-Tree的叶子节点只保存 TIDs,不保存真实数据,因此每个数据页能保存更多的叶子节点。跟 B+Tree相比,在相同数据量下,B-Tree高度更低。

PostgreSQL 索引中无论是内部节点还是叶子节点,数据都以递增顺序存储,同一层的数据页由双向链表连接。因此通过遍历链表就可以获取一个有序的数据集,范围查询并不需要中序遍历。

PostgreSQL 索引页格式如下,(下图来自官网):

image

下表对每个属性进行解释:

Item Description
PageHeaderData 24 bytes long. Contains general information about the page, including free space pointers.
ItemIdData Array of item identifiers pointing to the actual items. Each entry is an (offset,length) pair. 4 bytes per item.
Free space The unallocated space. New item identifiers are allocated from the start of this area, new items from the end.
Items The actual items themselves.
Special space Index access method specific data. Different methods store different data. Empty in ordinary tables.

三个优化

Deduplication

在索引中,如果存在大量相同的键值(比如一个被频繁更新的状态标志),PostgreSQL 会将这些重复的键值合并存储,只保留一个键值和多个对应的 TID 列表,这大大节省了空间,提高了缓存效率。

Index Only Scan

虽然叶子节点不保存完整数据,但叶子节点中除了存储键值和 TID,也可以保存查询中需要的某几个字段值(非索引列值),类似于覆盖索引。

这样,对于只查询索引列和包含列的语句,可以不用通过 TID 去堆上查找数据,直接通过索引就获取到查询结果。

反向键索引

PostgreSQL 可以创建反向排序的索引,这对于缓解插入热点(如递增主键、时间等字段)问题非常有效。创建索引的时候需要指定反向索引,例如下面 SQL 给员工编号(emp_id)创建一个反向键索引:

CREATE INDEX idx_emp_id ON tb_emploee(emp_id REVERSE);
总结

PostgreSQL 的索引结构虽然叫 B-Tree,但其实它实现了 B+Tree的功能,并且在索引上做了一些优化,使索引效率更高。

http://www.hskmm.com/?act=detail&tid=32515

相关文章:

  • Joeys shell
  • Redis 集群从部署到可视化管理全流程(超详细实战指南)
  • 什么是BPM流程自动化?从“财务报销”入手,一文读懂企业效率引擎
  • 软件工程学习日志2025.10.16
  • P1072 [NOIP 2009 提高组] Hankson 的趣味题
  • 25w41a快照测评:鹦鹉螺成精了?长矛教你戳穿末影人!
  • Day15-C:\Users\Lenovo\Desktop\note\code\JavaSE\Basic\src\com\classlei
  • Day14
  • window电脑开启hyperV虚拟化功能后导致本地服务端口被占用问题处理方案
  • RAG检索质量差?这5种分块策略帮你解决70%的问题
  • 初识pytorch:网络骨架中的填充之各种层
  • Day5字符型
  • 本地链路地址
  • 体育
  • Meta推出Agent Learning via Early Experience,推动语言代理自主学习新范式
  • Fiddler And LINQ - 特洛伊
  • 计算机视觉在自动化质检中的应用
  • 动态加速中优化失败路径反馈的方法
  • 铜价冲击下,如何“锁住”母排利润?
  • 前端快速开发工具推荐与实战 让开发速度提升 3 倍的完整工具链
  • js代码、js文件混淆、加密
  • Salesforce推出AI版Setup,说句话就能搞定配置?
  • 10.16读书报告
  • 火山引擎Data Agent再拓新场景,重磅推出用户研究Agent
  • 元推理:哥德尔搞不完定理,翻来覆去的搞。。。。
  • Matlab选择常见颜色
  • HyperWorks许可状态监控
  • 2025年纺丝机实力源头靠谱优质口碑厂家推荐,知名品牌纺丝机生产商哪家好?
  • 2025 年防静电地板源头厂家最新推荐榜单:权威品牌实力展现,助力各行业精准挑选优质产品
  • PostgreSQL社区CUUG 院校行 - 内蒙古农业大学计算机与信息工程学院