【数据库】PostgreSQL架构与索引深度剖析

PostgreSQL架构与索引深度剖析

前言

你维护了一个电商网站,需要存储千万级商品数据,你选了 MySQL。但随着业务发展,产品经理提了各种需求:地理位置搜索、全文检索、JSON 文档存储、时序数据分析...于是你引入了 Redis、Elasticsearch、MongoDB、InfluxDB,原本简单的单体架构变成了复杂的分布式系统。有没有一个数据库能原生支持这些需求?有,它就是 PostgreSQL。

🏠个人主页:你的主页


文章目录


一、PostgreSQL是什么

1.1 一句话定义

PostgreSQL(简称 PG)是一个功能最强大的开源关系型数据库,被称为"数据库天花板"。

1.2 为什么说它是天花板

PG 不仅能完全替代 MySQL,在很多场景下还能替代:

场景 传统方案 PG 替代方案
关系型存储 MySQL PG 原生支持
全文搜索 Elasticsearch PG + GIN 索引
文档存储 MongoDB PG + JSONB
地理信息 PostGIS/Redis GeoHash PG + GiST 索引
时序数据 InfluxDB PG + BRIN 索引
向量搜索 Milvus/Pinecone PG + pgvector 插件

一个数据库,多种索引,无限扩展

1.3 国产数据库的"祖师爷"

PG 完全开源可商用(BSD 协议),国内很多自研数据库都有 PG 的影子:

  • 阿里云 PolarDB(兼容 PG)
  • 腾讯云 TDSQL-PG
  • 华为 GaussDB(基于 PG)
  • 人大金仓 KingbaseES(基于 PG)
  • 瀚高数据库(基于 PG)

可以说,PG 养活了国内大半数据库团队。


二、存储架构详解

2.1 数据组织方式

PG 将数据组织成类似 Excel 表的结构:

复制代码
数据库(Database)
└── 模式(Schema)
    └── 表(Table)
        └── 行(Tuple)

与 MySQL 的区别

概念 MySQL PostgreSQL
数据库 Database Database
模式 不支持(或等同于 Database) Schema(一个 Database 可有多个 Schema)
Table Table/Relation
Row Tuple

PG 多了一层 Schema,可以在同一个数据库内实现更好的逻辑隔离。

2.2 堆表文件

数据表在磁盘上以**堆表文件(Heap File)**的形式存储:

复制代码
$PGDATA/base/<database_oid>/<relfilenode>
  • database_oid:数据库的 OID
  • relfilenode:表的文件节点号

举个例子

sql 复制代码
-- 查看表的存储位置
SELECT pg_relation_filepath('products');
-- 结果:base/16384/16385

2.3 数据页结构

当堆表文件超过 1GB 时,会自动拆分成多个文件(16385、16385.1、16385.2...)。

每个文件由多个 8KB 的数据页组成:

复制代码
┌─────────────────────────────────────────┐
│              Page Header                │ ← 24 字节,页面元信息
├─────────────────────────────────────────┤
│           Item Pointers                 │ ← 行指针数组,指向实际数据
│         (Line Pointers)                 │
├─────────────────────────────────────────┤
│                                         │
│            Free Space                   │ ← 空闲空间
│                                         │
├─────────────────────────────────────────┤
│              Tuples                     │ ← 实际行数据(从页尾向前增长)
│           (Row Data)                    │
├─────────────────────────────────────────┤
│           Special Space                 │ ← 特殊空间(索引页使用)
└─────────────────────────────────────────┘

与 MySQL InnoDB 的区别

特性 MySQL InnoDB PostgreSQL
页大小 16KB(默认) 8KB(默认)
行存储方式 聚簇索引(数据存在主键索引叶子节点) 堆表(数据和索引分离)
主键要求 必须有主键(没有会自动生成) 可以没有主键

2.4 MVCC 实现差异

PG 和 MySQL 都支持 MVCC(多版本并发控制),但实现方式完全不同。

MySQL InnoDB 的 MVCC

复制代码
原始数据行 → Undo Log(存储旧版本)
  • 更新时,旧版本数据写入 Undo Log
  • 通过 Undo Log 链回溯历史版本
  • Undo Log 会定期清理(Purge)

PostgreSQL 的 MVCC

复制代码
原始数据行(标记为删除) + 新数据行(插入)
  • 更新时,不修改原数据,而是插入一条新数据
  • 原数据标记 xmax(删除事务ID),新数据标记 xmin(创建事务ID)
  • 旧版本数据由 VACUUM 进程清理

打个比方

  • MySQL:像用橡皮擦掉旧内容,写上新内容,旧内容存在草稿纸上
  • PG:像在新的一行写新内容,旧的那行划掉但还在

各自的优缺点

特性 MySQL PostgreSQL
更新性能 原地更新,较快 插入新行,较慢
读取性能 需要回溯 Undo Log 直接读取,较快
空间占用 Undo Log 可能膨胀 表可能膨胀(需要 VACUUM)
回滚速度 需要应用 Undo Log 直接丢弃新行,很快

三、索引类型全解析

PG 之所以全能,核心在于它支持多种索引类型,且架构上支持扩展自定义索引。

3.1 B-Tree 索引(默认)

这是最常用的索引类型,适用于等值查询和范围查询。

sql 复制代码
CREATE INDEX idx_product_price ON products(price);

-- 等值查询
SELECT * FROM products WHERE price = 99;

-- 范围查询
SELECT * FROM products WHERE price BETWEEN 50 AND 100;

PG 的 B-Link Tree vs MySQL 的 B+Tree

MySQL 使用标准 B+Tree:

复制代码
        [30|60]              ← 非叶子节点
       /   |   \
    [10|20] [40|50] [70|80]  ← 叶子节点(双向链表)

PG 使用 B-Link Tree(Lehman-Yao 算法):

复制代码
        [30|60] →            ← 非叶子节点也有右指针
       /   |   \
    [10|20]→[40|50]→[70|80]  ← 叶子节点(单向链表)

B-Link Tree 的优势

  • 非叶子节点有右指针,页分裂时不需要锁整棵树
  • 并发性能更好,特别是高并发写入场景

3.2 GIN 索引(全文搜索)

GIN(Generalized Inverted Index,通用倒排索引)适用于全文搜索和数组查询。

原理:将文本分词,建立"词元 → 文档ID"的映射。

复制代码
文档1: "PostgreSQL 是最强数据库"
文档2: "MySQL 也是数据库"
文档3: "PostgreSQL 支持全文搜索"

分词后建立倒排索引:
┌──────────────┬─────────────┐
│     词元     │   文档ID    │
├──────────────┼─────────────┤
│ PostgreSQL   │ 1, 3        │
│ MySQL        │ 2           │
│ 数据库       │ 1, 2        │
│ 全文搜索     │ 3           │
└──────────────┴─────────────┘

使用示例

sql 复制代码
-- 创建全文搜索索引
CREATE INDEX idx_product_name_gin ON products USING gin(to_tsvector('chinese', name));

-- 全文搜索
SELECT * FROM products 
WHERE to_tsvector('chinese', name) @@ to_tsquery('chinese', '蓝牙 & 耳机');

GIN + JSONB:替代 MongoDB

sql 复制代码
-- 创建 JSONB 列的 GIN 索引
CREATE INDEX idx_product_attrs ON products USING gin(attributes jsonb_path_ops);

-- 查询 JSON 中包含特定键值对的记录
SELECT * FROM products 
WHERE attributes @> '{"color": "blue", "size": "L"}';

JSONB 是 PG 优化后的二进制 JSON 格式,配合 GIN 索引,百万级文档也能毫秒级查询。

3.3 GiST 索引(地理信息)

GiST(Generalized Search Tree,通用搜索树)是一个索引框架,支持多维数据。

R-Tree 原理

一维数据用线段表示范围,二维数据用矩形表示范围。

复制代码
        ┌─────────────────────────┐
        │      根节点矩形         │
        └───────────┬─────────────┘
              ┌─────┴─────┐
              ↓           ↓
        ┌─────────┐ ┌─────────┐
        │ 矩形A   │ │ 矩形B   │
        └────┬────┘ └────┬────┘
             ↓           ↓
          [点1,点2]   [点3,点4]

查询"附近 1 公里的店铺"时:

  1. 计算查询点周围 1 公里的矩形范围
  2. 从根节点开始,找与查询矩形相交的子矩形
  3. 递归向下,最终找到叶子节点的坐标点

使用示例

sql 复制代码
-- 启用 PostGIS 扩展
CREATE EXTENSION postgis;

-- 创建地理位置列和索引
ALTER TABLE stores ADD COLUMN location geometry(Point, 4326);
CREATE INDEX idx_store_location ON stores USING gist(location);

-- 查询上海市中心 1 公里内的店铺
SELECT name, ST_Distance(location, ST_SetSRID(ST_MakePoint(121.4737, 31.2304), 4326)) as distance
FROM stores
WHERE ST_DWithin(
    location, 
    ST_SetSRID(ST_MakePoint(121.4737, 31.2304), 4326), 
    1000  -- 1000米
)
ORDER BY distance;

3.4 BRIN 索引(时序数据)

BRIN(Block Range Index,块范围索引)适用于按时间或 ID 顺序插入的大数据表。

原理:不为每行数据建索引,而是为每批数据页记录范围摘要。

复制代码
┌─────────────────────────────────────────────────┐
│ 页范围 │ 最小时间          │ 最大时间          │
├────────┼───────────────────┼───────────────────┤
│ 1-128  │ 2025-01-01 00:00 │ 2025-01-15 23:59 │
│ 129-256│ 2025-01-16 00:00 │ 2025-01-31 23:59 │
│ 257-384│ 2025-02-01 00:00 │ 2025-02-15 23:59 │
└────────┴───────────────────┴───────────────────┘

查询 2025-02-10 的数据时,直接定位到 257-384 页范围,跳过其他页。

使用示例

sql 复制代码
-- 创建 BRIN 索引
CREATE INDEX idx_logs_created_at ON logs USING brin(created_at);

-- 查询某天的日志
SELECT * FROM logs WHERE created_at BETWEEN '2025-02-10' AND '2025-02-11';

BRIN vs B-Tree 对比

特性 B-Tree BRIN
索引大小 大(每行一个条目) 极小(每批页一个条目)
查询精度 精确 粗略(需要扫描范围内的页)
适用场景 随机数据 顺序插入的数据(时间、自增ID)
维护成本

打个比方

  • B-Tree 像书的详细目录,精确到每一节
  • BRIN 像书的章节目录,只告诉你大概在哪个章节

3.5 Hash 索引

适用于等值查询,不支持范围查询。

sql 复制代码
CREATE INDEX idx_product_sku ON products USING hash(sku);

-- 只支持等值查询
SELECT * FROM products WHERE sku = 'SKU-12345';

注意:PG 10 之前 Hash 索引不记录 WAL,崩溃后需要重建。PG 10+ 已修复。

3.6 索引类型总结

索引类型 适用场景 可替代的中间件
B-Tree 等值、范围查询 MySQL
GIN 全文搜索、JSONB、数组 Elasticsearch、MongoDB
GiST 地理位置、多维数据 PostGIS、Redis GeoHash
BRIN 时序数据、顺序插入 InfluxDB
Hash 等值查询 -

四、进程架构详解

4.1 多进程 vs 多线程

MySQL:多线程架构

复制代码
mysqld 进程
├── 连接线程1
├── 连接线程2
├── 连接线程3
└── 后台线程(IO、Purge等)

PostgreSQL:多进程架构

复制代码
Postmaster(主进程)
├── Backend Process 1(后端进程)
├── Backend Process 2
├── Backend Process 3
└── Background Workers(后台进程)

各自的优缺点

特性 MySQL(多线程) PostgreSQL(多进程)
内存占用 低(线程共享内存) 高(每个进程独立内存)
稳定性 一个线程崩溃可能影响整个进程 一个进程崩溃不影响其他进程
并发连接 支持更多连接 连接数受限(需要连接池)
上下文切换

4.2 Postmaster 主进程

Postmaster 是 PG 的"指挥中心":

  • 监听客户端连接请求

  • 为每个新连接 Fork 出后端进程

  • 监控所有子进程的健康状态

  • 管理共享内存

    客户端连接请求

    Postmaster 接收

    Fork 后端进程

    后端进程处理请求

4.3 Backend Process 后端进程

每个客户端连接对应一个后端进程(也叫 Postgres 进程)。

bash 复制代码
# 查看 PG 进程
ps aux | grep postgres

postgres  1234  postgres: user db 127.0.0.1(54321) idle
postgres  1235  postgres: user db 127.0.0.1(54322) SELECT
postgres  1236  postgres: user db 127.0.0.1(54323) UPDATE waiting

问题:如果应用有 500 个连接,就要创建 500 个进程,内存消耗巨大。

解决方案:使用连接池

  • PgBouncer:轻量级连接池,推荐

  • Pgpool-II:功能更丰富,支持负载均衡

    应用(500连接) → PgBouncer(连接池) → PostgreSQL(50进程)

4.4 Background Workers 后台进程

PG 有多个后台进程负责维护工作:

进程名 职责
Background Writer 持续将脏页写入磁盘,减少 Checkpoint 压力
Checkpointer 定期将所有脏页强制写入磁盘
WAL Writer 将 WAL 缓冲区写入磁盘
Autovacuum Launcher 启动自动 VACUUM 进程
Autovacuum Worker 执行 VACUUM 清理死元组
Stats Collector 收集统计信息
Logical Replication 逻辑复制相关

VACUUM 是什么?

前面说过,PG 更新数据时不删除旧行,而是标记为"死元组"。VACUUM 就是清理这些死元组的进程。

sql 复制代码
-- 手动执行 VACUUM
VACUUM products;

-- VACUUM FULL(重建表,会锁表)
VACUUM FULL products;

-- 查看表的死元组数量
SELECT relname, n_dead_tup FROM pg_stat_user_tables;

与 MySQL 的对比

特性 MySQL PostgreSQL
旧版本清理 Purge 线程清理 Undo Log VACUUM 进程清理死元组
是否需要手动干预 一般不需要 大表可能需要调优 VACUUM
表膨胀问题 较少 可能发生(需要关注)

五、内存架构详解

5.1 共享内存区域

所有后端进程共享的内存区域:

复制代码
┌─────────────────────────────────────────────────────┐
│                   Shared Memory                     │
├─────────────────────────────────────────────────────┤
│  ┌─────────────────────────────────────────────┐   │
│  │           Shared Buffer Pool                │   │ ← 缓存数据页
│  │              (shared_buffers)               │   │
│  └─────────────────────────────────────────────┘   │
│  ┌─────────────────────────────────────────────┐   │
│  │             WAL Buffer                      │   │ ← WAL 日志缓冲
│  │            (wal_buffers)                    │   │
│  └─────────────────────────────────────────────┘   │
│  ┌─────────────────────────────────────────────┐   │
│  │           CLOG Buffer                       │   │ ← 事务状态缓存
│  └─────────────────────────────────────────────┘   │
│  ┌─────────────────────────────────────────────┐   │
│  │         Lock Space / Other                  │   │ ← 锁信息等
│  └─────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────┘

5.2 Shared Buffer Pool

这是 PG 最重要的内存区域,用于缓存数据页和索引页。

sql 复制代码
-- 查看 shared_buffers 配置
SHOW shared_buffers;

-- 推荐设置为物理内存的 25%
-- postgresql.conf
shared_buffers = 4GB

工作流程

复制代码
后端进程查询数据
      ↓
检查 Shared Buffer Pool
      ├── 命中 → 直接返回
      └── 未命中 → 从磁盘读取 → 放入 Buffer Pool → 返回

与 MySQL Buffer Pool 的区别

特性 MySQL InnoDB Buffer Pool PostgreSQL Shared Buffers
默认大小 128MB 128MB
推荐大小 物理内存的 50-80% 物理内存的 25%
为什么 PG 推荐更小? - PG 依赖操作系统的文件缓存

5.3 进程私有内存

每个后端进程还有自己的私有内存:

内存区域 用途 配置参数
work_mem 排序、哈希操作 work_mem
maintenance_work_mem VACUUM、CREATE INDEX maintenance_work_mem
temp_buffers 临时表 temp_buffers
sql 复制代码
-- 查看 work_mem
SHOW work_mem;  -- 默认 4MB

-- 大查询可以临时调大
SET work_mem = '256MB';
SELECT * FROM big_table ORDER BY column1;

注意work_mem 是每个操作的内存,一个查询可能有多个排序操作,总内存 = work_mem × 操作数 × 连接数。


六、WAL日志机制

6.1 为什么需要 WAL

数据在 Shared Buffer 中更新后,如果还没写入磁盘就崩溃了,数据就丢了。

解决方案:Write-Ahead Logging(预写日志)

  • 先写日志,再写数据
  • 崩溃后通过日志恢复数据

6.2 WAL 工作流程

复制代码
1. 事务开始
2. 修改 Shared Buffer 中的数据页
3. 将修改操作写入 WAL Buffer
4. 事务提交时,WAL Buffer 刷入磁盘(WAL 文件)
5. 后台进程异步将脏页刷入磁盘
6. 崩溃恢复时,重放 WAL 日志

为什么先写 WAL 而不是直接写数据页?

  • WAL 是顺序写 ,数据页是随机写
  • 顺序写磁盘性能是随机写的几十倍

6.3 WAL 文件结构

复制代码
$PGDATA/pg_wal/
├── 000000010000000000000001
├── 000000010000000000000002
├── 000000010000000000000003
└── ...

每个 WAL 文件默认 16MB

6.4 与 MySQL Redo Log 的对比

特性 MySQL Redo Log PostgreSQL WAL
文件结构 固定大小,循环写入 持续增长,归档后删除
默认大小 48MB(2个文件×24MB) 无上限(可配置保留策略)
用途 崩溃恢复 崩溃恢复 + 复制 + PITR

PITR(Point-In-Time Recovery)

PG 可以通过 WAL 归档实现任意时间点恢复:

bash 复制代码
# 恢复到指定时间点
recovery_target_time = '2025-02-15 14:30:00'

七、查询执行流程

7.1 完整流程

复制代码
┌─────────────────────────────────────────────────────────────┐
│                      Backend Process                        │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────┐   ┌─────────┐   ┌─────────┐   ┌─────────────┐ │
│  │ Parser  │ → │ Analyzer│ → │ Planner │ → │  Executor   │ │
│  │ (解析器) │   │ (分析器) │   │ (优化器) │   │  (执行器)   │ │
│  └─────────┘   └─────────┘   └─────────┘   └──────┬──────┘ │
│                                                    ↓        │
│                                          ┌─────────────────┐│
│                                          │ Access Methods  ││
│                                          │   (访问方法)     ││
│                                          └────────┬────────┘│
└───────────────────────────────────────────────────┼─────────┘
                                                    ↓
                              ┌──────────────────────────────────┐
                              │         Shared Memory            │
                              │  ┌────────────┐ ┌────────────┐  │
                              │  │Buffer Pool │ │ WAL Buffer │  │
                              │  └────────────┘ └────────────┘  │
                              └──────────────────────────────────┘
                                                    ↓
                              ┌──────────────────────────────────┐
                              │            Disk                  │
                              │  ┌────────────┐ ┌────────────┐  │
                              │  │ Data Files │ │ WAL Files  │  │
                              │  └────────────┘ └────────────┘  │
                              └──────────────────────────────────┘

7.2 各模块职责

Parser(解析器)

  • 检查 SQL 语法是否正确
  • 生成解析树(Parse Tree)

Analyzer(分析器)

  • 检查表、列是否存在
  • 检查权限
  • 生成查询树(Query Tree)

Planner/Optimizer(优化器)

  • 选择使用哪个索引
  • 选择 Join 方式(Nested Loop、Hash Join、Merge Join)
  • 生成执行计划(Plan Tree)

Executor(执行器)

  • 按执行计划调用 Access Methods
  • 返回结果

7.3 查看执行计划

sql 复制代码
EXPLAIN ANALYZE SELECT * FROM products WHERE price > 100;

                                                 QUERY PLAN
------------------------------------------------------------------------------------------------------------
 Index Scan using idx_product_price on products  (cost=0.29..8.31 rows=1 width=100) (actual time=0.015..0.016 rows=1 loops=1)
   Index Cond: (price > 100)
 Planning Time: 0.080 ms
 Execution Time: 0.030 ms

7.4 Access Methods(访问方法)

Access Methods 是 PG 扩展性的核心,它定义了如何访问不同类型的数据。

复制代码
Access Methods
├── Heap AM(堆表访问)
├── Index AM(索引访问)
│   ├── B-Tree
│   ├── GIN
│   ├── GiST
│   ├── BRIN
│   └── Hash
└── 自定义 AM(插件扩展)

通过开放 Access Methods 接口,用户可以扩展支持:

  • 向量搜索(pgvector)
  • 图数据库(Apache AGE)
  • 列式存储(Citus)

八、PostgreSQL vs MySQL 深度对比

8.1 架构对比

特性 MySQL PostgreSQL
进程模型 多线程 多进程
存储引擎 可插拔(InnoDB、MyISAM等) 单一(堆表)
索引与数据 聚簇索引(数据在主键索引中) 分离(堆表 + 索引)
MVCC 实现 Undo Log 多版本元组
连接管理 线程池 需要外部连接池

8.2 功能对比

功能 MySQL PostgreSQL
JSON 支持 JSON(5.7+) JSONB(更强大)
全文搜索 支持(较弱) 原生支持(GIN 索引)
地理信息 需要扩展 PostGIS(业界标准)
数组类型 不支持 原生支持
自定义类型 不支持 支持
物化视图 不支持 支持
CTE(WITH 语句) 8.0+ 支持 一直支持
窗口函数 8.0+ 支持 一直支持
表继承 不支持 支持
外部数据包装器 不支持 FDW(可查询外部数据源)

8.3 SQL 标准兼容性

PostgreSQL 对 SQL 标准的支持更完整:

sql 复制代码
-- PostgreSQL 支持的高级特性

-- 1. 数组操作
SELECT ARRAY[1, 2, 3] || ARRAY[4, 5];  -- {1,2,3,4,5}

-- 2. JSONB 操作
SELECT '{"name": "test"}'::jsonb -> 'name';  -- "test"
SELECT '{"name": "test"}'::jsonb ->> 'name'; -- test(文本)

-- 3. 范围类型
SELECT '[2025-01-01, 2025-12-31]'::daterange @> '2025-06-15'::date;  -- true

-- 4. 递归 CTE
WITH RECURSIVE subordinates AS (
    SELECT id, name, manager_id FROM employees WHERE id = 1
    UNION ALL
    SELECT e.id, e.name, e.manager_id 
    FROM employees e 
    JOIN subordinates s ON e.manager_id = s.id
)
SELECT * FROM subordinates;

-- 5. 窗口函数
SELECT name, salary, 
       RANK() OVER (ORDER BY salary DESC) as rank,
       SUM(salary) OVER () as total
FROM employees;

8.4 性能对比

读性能

场景 MySQL PostgreSQL
简单主键查询 快(聚簇索引) 稍慢(需要回表)
复杂查询 一般 更好(优化器更强)
全文搜索

写性能

场景 MySQL PostgreSQL
单行更新 快(原地更新) 稍慢(插入新行)
批量插入
高并发写入 好(B-Link Tree 优势)

总结

  • 简单 CRUD:MySQL 略快
  • 复杂查询:PostgreSQL 更强
  • 特殊数据类型:PostgreSQL 完胜

8.5 运维对比

方面 MySQL PostgreSQL
学习曲线 平缓 稍陡
社区资源 非常丰富 丰富
云服务支持 所有云厂商 所有云厂商
主从复制 成熟 成熟
高可用方案 MHA、MGR、Orchestrator Patroni、repmgr
需要关注的问题 主从延迟 VACUUM、表膨胀

8.6 如何选择

选 MySQL 的场景

  • 团队熟悉 MySQL
  • 简单的 CRUD 业务
  • 对运维复杂度敏感
  • 需要大量社区资源和教程

选 PostgreSQL 的场景

  • 需要复杂查询和分析
  • 需要 JSON 文档存储
  • 需要地理信息处理
  • 需要全文搜索
  • 需要时序数据存储
  • 追求 SQL 标准兼容
  • 需要高度可扩展性

一句话总结

  • MySQL:简单、够用、生态好
  • PostgreSQL:强大、全能、天花板

九、总结

9.1 核心架构回顾

组件 说明
Postmaster 主进程,管理连接和子进程
Backend Process 后端进程,处理客户端请求
Shared Buffer 共享缓冲区,缓存数据页
WAL Buffer WAL 缓冲区,缓存日志
Background Workers 后台进程,VACUUM、Checkpoint 等

9.2 索引能力总结

索引 能力 可替代
B-Tree 等值、范围查询 MySQL
GIN 全文搜索、JSONB Elasticsearch、MongoDB
GiST 地理位置、多维数据 PostGIS
BRIN 时序数据 InfluxDB

9.3 与 MySQL 的核心差异

差异点 MySQL PostgreSQL
进程模型 多线程 多进程
MVCC Undo Log 多版本元组
索引类型 主要是 B+Tree 多种索引
扩展性 存储引擎可插拔 Access Methods 可扩展
功能丰富度 够用 天花板

最后一句话:PostgreSQL 是数据库领域的"全干工程师",一个数据库顶多个中间件。如果你的业务需求复杂多变,PG 绝对是值得投资学习的选择。


热门专栏推荐

等等等还有许多优秀的合集在主页等着大家的光顾,感谢大家的支持

文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😊

希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🙏

如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🌟

相关推荐
不穿格子的程序员2 小时前
Redis篇6——Redis深度剖析:从单机到集群,Redis高可用进化史
数据库·redis·集群·主从·高可用·哨兵
阿坤带你走近大数据2 小时前
什么是元数据管理?(附具体实施方案供参考)
数据库·金融
xiliuhu2 小时前
PgSQL高级用法
postgresql
俊男无期2 小时前
超效率工作法
java·前端·数据库
2301_823438022 小时前
【无标题】解析《采用非对称自玩实现强健多机器人群集的深度强化学习方法》
数据库·人工智能·算法
中国胖子风清扬2 小时前
SpringAI和 Langchain4j等 AI 框架之间的差异和开发经验
java·数据库·人工智能·spring boot·spring cloud·ai·langchain
Elastic 中国社区官方博客3 小时前
Elasticsearch:你是说,用于混合搜索(hybrid search)
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
czlczl200209253 小时前
高并发下的 Token 存储策略: Redis 与 MySQL 的一致性
数据库·redis·mysql
虹科网络安全3 小时前
艾体宝产品 | 基准测试:ArangoDB性能碾压Neo4j,速度最高提升8倍!
数据库·neo4j