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

MySQL和PostgreSQL的数据库主键索引都是B+树吗?

这是一个非常好的问题,答案是:基本上是的,但两者在实现细节和设计哲学上有重要区别。

简单来说:

  • MySQL(默认的InnoDB存储引擎):主键索引是 B+Tree,并且是 聚集索引(Clustered Index)
  • PostgreSQL:主键索引默认也是基于 B-Tree 的,但 PostgreSQL 使用的是 堆表(Heap Table) 结构。

下面我们来详细解释这两者的区别和为什么都倾向于使用这种数据结构。

核心共同点:为什么都是 B-Tree(或其变种)?

无论是 MySQL 的 B+Tree 还是 PostgreSQL 的 B-Tree,它们都是一种 平衡多路搜索树。这种数据结构非常适合作为数据库索引,因为它具有以下优点:

  1. 查询效率高:查找、插入、删除、更新的时间复杂度都是 O(log n)n 是记录数。这意味着即使表中有数十亿条记录,只需很少的磁盘 I/O(树的深度很低)就能找到数据。
  2. 适合磁盘存储:树的一个节点通常被设计为与一个磁盘页(Page)或块(Block)的大小(如 4KB, 8KB, 16KB)相匹配。每次磁盘 I/O 可以读取一个完整的节点,极大减少了磁盘访问次数。
  3. 范围查询高效:所有数据项都按顺序存储在叶子节点上,这对于 WHERE id BETWEEN 10 AND 100 这类范围查询非常高效,只需要找到起始点,然后顺序遍历叶子节点即可。

MySQL (InnoDB) 的 B+Tree 实现

  1. 索引类型B+Tree
  2. 表结构聚集索引(Clustered Index)

这是最关键的区别。在 InnoDB 中:

  • 表数据本身就存储在主键索引的 B+Tree 的叶子节点上。换句话说,叶子节点不仅包含了主键值,还包含了该行所有其他列的数据(除了 TEXT/BLOB 等可能被溢出存储的类型)。
  • 因此,每个表必须有且只有一个聚集索引。如果你定义了主键(PRIMARY KEY),那么主键索引就是这个聚集索引。如果没有定义主键,InnoDB 会选择一个唯一的非空索引代替,如果也没有,则会隐式创建一个隐藏的聚簇索引。
  • 二级索引(Secondary Index) 的叶子节点存储的不是行数据,而是该行对应的主键值。这意味着通过二级索引查找数据时,需要先找到主键值,再回到主键索引(聚簇索引)树中查找完整的行数据。这个过程称为 回表(Bookmark Lookup)

优点

  • 对于主键的点查和范围查询速度极快,因为数据就在同一棵树上。
  • 数据按主键顺序存储,对于主键排序的查询效率高。

缺点

  • 如果主键值不是顺序增长的(例如使用 UUID),插入新数据可能导致页分裂,影响写入性能并产生碎片。
  • 二级索引查询需要两次索引查找(回表),可能会慢一些。

PostgreSQL 的 B-Tree 实现

  1. 索引类型B-Tree (PostgreSQL 的官方文档一直称之为 B-Tree,但其现代实现与经典的 B-Tree 更接近,与 B+Tree 的思想类似,叶子节点也包含所有数据项并按顺序链接,但具体实现是它自己的优化版本。我们可以近似地将其核心原理理解为 B+Tree。)
  2. 表结构堆表(Heap Table)

这是与 MySQL 最根本的不同。在 PostgreSQL 中:

  • 表数据以一种堆(Heap) 的形式存储。所谓“堆”,就是一种无序的数据结构,行数据写入时只需找到空闲空间存放即可,并不强制按主键顺序存储。
  • 主键索引其他二级索引都是独立的 B-Tree 结构。这些索引的叶子节点不存储完整的行数据,而是存储一个指向堆表中该行物理位置(称为 TID(Tuple ID),由页面号和页内偏移量组成)的指针。
  • 当通过索引查询时,PostgreSQL 先在索引树中找到对应的 TID,然后再根据这个 TID 指针去堆数据表中读取真正的行数据。

优点

  • 表数据独立于索引,对主键的插入顺序不敏感,减少了页分裂问题。
  • 所有索引在结构上是平等的,二级索引查询不需要像 MySQL 那样“回表”到主键索引,而是直接通过 TID 访问数据堆。(虽然仍然是两次查找,但路径不同)。
  • 支持多版本并发控制(MVCC) 的实现更方便,因为同一行数据的多个版本可以共存于堆中,索引的 TID 可以指向不同的版本。

缺点

  • 由于数据存储无序,全表扫描可能不如按主键顺序存储的聚集索引高效。
  • 索引查询总是需要额外的跳转(通过 TID),理论上比直接从索引叶子节点取数据多一次随机 I/O(但 PostgreSQL 有优化,如仅索引扫描)。

总结对比

特性MySQL (InnoDB)PostgreSQL
索引结构B+TreeB-Tree (类 B+Tree 实现)
表组织方式聚集索引(Clustered Index)堆表(Heap Table)
主键索引叶子节点内容完整的行数据指向堆表中行位置的指针(TID)
二级索引叶子节点内容主键值指向堆表中行位置的指针(TID)
通过主键查询一次查找,直接获取数据一次索引查找 + 一次堆表访问
通过二级索引查询两次索引查找(回表)一次索引查找 + 一次堆表访问
数据存储顺序按主键顺序存储按插入顺序存储(实际取决于空闲空间)

扩展:PostgreSQL 的更多索引类型

值得一提的是,PostgreSQL 以其强大的扩展性著称,它不仅支持 B-Tree 索引,还内置了多种其他索引类型,适用于不同的场景:

  • GIN (Generalized Inverted Index): 用于处理数组、JSONB、全文搜索等“包含”查询。
  • GiST (Generalized Search Tree): 一种允许构建多种搜索策略(如几何图形、范围类型、全文搜索)的通用索引框架。
  • SP-GiST (Space-Partitioned GiST): 适用于非平衡数据结构(如四叉树、k-d 树)的索引。
  • BRIN (Block Range INdexes): 对于非常庞大的、按物理顺序存储的表(如时间序列数据)非常高效,它存储连续数据块的范围摘要。
  • Hash: 仅支持等值查询,通常不如 B-Tree 实用。

而 MySQL 的 InnoDB 目前只支持 B-Tree(实际上是 B+Tree)索引,但它的自适应哈希索引(Adaptive Hash Index)会在内存中自动为热点页构建哈希索引以加速查询。

结论:
两者默认都使用 B-Tree(或其变种 B+Tree)来实现主键索引,因为它们是为磁盘存储设计的数据库的最佳选择之一。最大的区别在于表数据的组织方式:MySQL 使用聚集索引,而 PostgreSQL 使用堆表。 这个根本差异导致了它们在数据存储、索引查询路径和性能特性上的一系列不同。

http://www.dtcms.com/a/406526.html

相关文章:

  • VUE、jquery、React、Ant Design、element ui、bootstrap 前端框架的 功能总结,示例演示、使用场景介绍、完整对比总结
  • PDF格式转换、PDF编辑全功能解锁,功能图文教程
  • C++项目:仿muduo库高并发服务器
  • 建设网站业务不好做请问那个网站做推广好点
  • Pytest+requests进行接口自动化测试6.0(Jenkins)
  • elasticsearch安装插件
  • html5移动网站开发html5新增标签
  • 前端工程化基础知识
  • 【C#】以 BlockingCollection 为核心的多相机 YOLO 检测任务处理框架
  • (11)ASP.NET Core2.2 中的配置一(Configuration)
  • 在 C# .NETCore 中使用 MongoDB(第 1 部分):驱动程序基础知识和插入文档
  • php做图片交互网站代码网站下要加个备案号 怎么做
  • 巴中商城网站建设wordpress 图书主题
  • 一键预约上门服务:到家洗车小程序的便捷功能与场景化体验
  • 第 3 篇:让图形动起来 - WebGL 2D 变换
  • 寝室快修|基于SprinBoot+vue的贵工程寝室快修小程序(源码+数据库+文档)
  • 青秀网站建设网站海外推广平台
  • 前端基础:从0到1实现简单网页效果(二)
  • 基于LazyLLM搭建AI创意文案生成器(多场景文案自动生成)
  • 数据链路层:网络通信的基础与桥梁
  • Keepalived两个集群实验
  • vs网站开发表格大小设置网站建设要注意一些什么
  • js网站模板下载做网站和app哪个难
  • MySQL多实例管理
  • 用dpdk实现udp、tcp数据包收发,tcp协议栈相关原理
  • 3D气象数据可视化:使用前端框架实现动态天气展示
  • 学习日记19:GRAPH-BERT
  • shell编程:sed - 流编辑器(5)
  • 网站制作地点中山网站建设公司哪家好
  • 关于【机器人小脑】的快速入门介绍