PostgreSQL 原理、架构与设计思想详解

PostgreSQL 原理、架构与设计思想详解

PostgreSQL 原理、架构与设计思想详解

世界上最先进的开源关系型数据库系统

info PostgreSQL 简介

PostgreSQL是一个功能强大的开源对象-关系型数据库系统(ORDBMS),起源于加州大学伯克利分校的POSTGRES项目,已有超过30年的开发历史。它支持大部分SQL标准,并提供了许多现代特性,如复杂查询、外键、触发器、视图、事务完整性和多版本并发控制(MVCC)等。
PostgreSQL以其高度的可靠性、数据完整性和对复杂查询的支持而闻名,被广泛用于各种规模的应用程序,从个人项目到大型企业级系统。它采用灵活的BSD许可证,允许用户自由使用、修改和分发,无论是私用、商用还是学术研究。

历史发展

PostgreSQL的发展历程可以追溯到1986年,当时加州大学伯克利分校的Michael Stonebraker教授领导的POSTGRES项目开始。经过多年的发展,项目在1996年正式更名为PostgreSQL,标志着从POSTGRES到现代PostgreSQL的转变。以下是PostgreSQL发展的几个关键里程碑:
  • 1986年:POSTGRES项目启动
  • 1995年:添加SQL解释器,发布Postgres95
  • 1996年:正式更名为PostgreSQL
  • 2010年:支持NoSQL特性,如JSON数据类型
  • 2017年:支持逻辑复制和分区表
  • 2020年:支持增强的并行查询和JIT编译
  • 2025年:引入异步I/O框架,进一步提升性能

architecture PostgreSQL 架构

PostgreSQL采用客户端/服务器架构,由多个进程组成,每个进程负责特定的功能。这种架构设计使得PostgreSQL能够高效地处理并发请求,并保持系统的稳定性和可靠性。

进程结构

PostgreSQL的进程结构主要包括以下几种类型的进程:
  • Postmaster进程:主进程,负责启动和关闭数据库服务器,管理其他进程
  • 服务器进程:处理客户端连接,每个客户端连接对应一个服务器进程
  • 后台进程:执行特定任务的后台进程,如检查点进程、WAL写入进程、自动清理进程等
  • 辅助进程:如统计收集进程、归档进程等
bash
# 查看PostgreSQL进程
ps aux | grep postgres

# 典型输出示例:
# postgres  1234  0.0  0.1  123456 7890 ?        S    10:00   0:00 /usr/lib/postgresql/14/bin/postgres
# postgres  1235  0.0  0.0  123456 2345 ?        Ss   10:00   0:00 postgres: logger
# postgres  1237  0.0  0.0  123456 3456 ?        Ss   10:00   0:00 postgres: checkpointer
# postgres  1238  0.0  0.0  123456 4567 ?        Ss   10:00   0:00 postgres: writer
# postgres  1239  0.0  0.0  123456 5678 ?        Ss   10:00   0:00 postgres: wal writer
# postgres  1240  0.0  0.0  123456 6789 ?        Ss   10:00   0:00 postgres: autovacuum launcher
# postgres  1241  0.0  0.0  123456 7890 ?        Ss   10:00   0:00 postgres: stats collector
# postgres  1242  0.0  0.0  123456 8901 ?        Ss   10:00   0:00 postgres: logical replication launcher

内存结构

PostgreSQL的内存结构主要包括共享内存和本地内存两部分:
  • 共享内存:由所有后端进程共享,主要包括共享缓冲区、WAL缓冲区、锁表等
  • 本地内存:每个后端进程独有,包括工作内存、临时缓冲区等
共享内存
共享缓冲区 (shared_buffers)
WAL缓冲区 (wal_buffers)
锁表 (lock table)
共享查询表 (shared catalog)
本地内存
工作内存 (work_mem)
维护工作内存 (maintenance_work_mem)
临时缓冲区 (temp_buffers)

存储结构

PostgreSQL的存储结构是基于表的物理存储,每个表对应一个或多个文件,存储在数据目录中。主要存储组件包括:
  • 表空间:逻辑存储单元,可以映射到操作系统的不同目录
  • 数据库:表空间的子集,包含多个模式
  • 模式:数据库的逻辑分组,包含表、索引、函数等对象
  • 表和索引:实际存储数据的结构,以堆表形式组织
sql
-- 查看表空间信息
SELECT spcname AS "表空间名称",
       pg_tablespace_location(oid) AS "位置"
FROM pg_tablespace;

-- 查看数据库存储信息
SELECT datname AS "数据库名称",
       pg_database_size(datname) AS "大小"
FROM pg_database
ORDER BY pg_database_size(datname) DESC;

settings PostgreSQL 核心原理

多版本并发控制 (MVCC)

MVCC (Multi-Version Concurrency Control) 是PostgreSQL实现并发控制的核心机制,它允许读操作和写操作同时进行而不互相阻塞。在PostgreSQL中,当一行记录被更新时,不会直接修改原记录,而是创建一个新版本,旧版本仍然保留,直到不再被任何事务需要。
PostgreSQL的MVCC实现方式与Oracle和MySQL/InnoDB不同。Oracle和MySQL/InnoDB使用回滚段(undo log)来存储旧版本数据,而PostgreSQL则直接在表中保留多个版本的数据行,通过事务ID和事务状态来控制数据的可见性。
sql
-- 查看系统列,了解MVCC实现
SELECT xmin, xmax, ctid, * FROM your_table LIMIT 5;

-- xmin: 创建该行版本的事务ID
-- xmax: 删除或更新该行版本的事务ID
-- ctid: 行的物理位置,包含块号和块内偏移量
每个行版本(称为tuple)都包含以下关键信息:
  • xmin:插入或更新该行版本的事务ID
  • xmax:删除或更新该行版本的事务ID,初始为null
  • 事务状态:存储在CLOG(Transaction Commit Log)中,包含事务的状态(in-progress, committed, aborted)
lightbulb MVCC可见性规则
一个行版本对当前事务可见的条件是: 1. 创建该行版本的事务已提交(xmin有效且已提交) 2. 删除该行版本的事务未提交或不存在(xmax无效或未提交) 3. 当前事务不是创建该行版本的事务(避免看到自己未提交的更改)
由于MVCC机制,PostgreSQL需要定期清理过期和已删除的行版本,这个过程称为VACUUM。PostgreSQL提供了自动VACUUM机制,由autovacuum进程定期执行,以回收磁盘空间并更新统计信息。

预写日志 (WAL)

WAL (Write-Ahead Logging) 是PostgreSQL确保数据持久性和崩溃恢复的核心机制。WAL的基本原理是:在对数据文件进行任何修改之前,先将这些修改记录到日志中。这样即使系统崩溃,也可以通过重放WAL日志来恢复数据,保证事务的持久性。
WAL的主要组成部分包括:
  • WAL记录:描述对数据库所做的更改
  • WAL缓冲区:内存中的WAL记录缓冲区
  • WAL段文件:磁盘上的WAL文件,默认大小为16MB
  • 检查点(Checkpoint):定期将缓冲区中的脏页写入磁盘,并记录检查点位置
sql
-- 查看WAL配置参数
SHOW wal_level;
SHOW wal_buffers;
SHOW checkpoint_timeout;
SHOW max_wal_size;

-- 查看WAL文件信息
SELECT pg_walfile_name(pg_current_wal_lsn());
WAL的工作流程如下:
  1. 事务修改数据时,先将修改记录到WAL缓冲区
  2. WAL写入进程定期将WAL缓冲区的内容写入磁盘上的WAL段文件
  3. 当事务提交时,确保WAL记录已写入磁盘
  4. 后台进程定期将缓冲区中的脏页写入磁盘(检查点)
  5. 系统崩溃后,通过重放检查点后的WAL记录来恢复数据
new_releases PostgreSQL 18 新特性:异步I/O框架
PostgreSQL 18引入了全新的异步I/O子系统,允许在特定场景下并行执行多个异步预读操作,CPU无需等待数据返回即可继续推进查询,降低了等待损耗。目前异步I/O已支持顺序扫描、位图堆扫描和VACUUM操作的异步读取,早期测试显示,读取密集型查询性能可提升2-3倍。

查询优化器

PostgreSQL的查询优化器负责将SQL查询转换为高效的执行计划。它是一个基于成本的优化器(Cost-Based Optimizer, CBO),通过估算不同执行路径的成本,选择成本最低的执行计划。
查询优化过程主要包括以下步骤:
  1. 解析和重写查询
  2. 生成可能的执行路径
  3. 估算每个执行路径的成本
  4. 选择成本最低的执行计划
sql
-- 查看查询执行计划
EXPLAIN SELECT * FROM employees WHERE department_id = 10;

-- 查看详细的执行计划和成本估算
EXPLAIN ANALYZE SELECT * FROM employees WHERE department_id = 10;
PostgreSQL优化器考虑的成本因素包括:
  • I/O成本:从磁盘读取数据页的成本
  • CPU成本:处理数据的计算成本
  • 内存使用:执行计划所需的内存量
  • 网络开销:在分布式环境中的网络传输成本
PostgreSQL支持多种扫描方法和连接策略,优化器会根据表大小、可用索引、统计信息等因素选择最合适的执行策略:
  • 扫描方法:顺序扫描(Seq Scan)、索引扫描(Index Scan)、位图扫描(Bitmap Scan)等
  • 连接策略:嵌套循环连接(Nested Loop)、哈希连接(Hash Join)、归并连接(Merge Join)等

lightbulb PostgreSQL 设计思想

PostgreSQL的设计哲学体现了开源社区对数据库系统的深刻理解和创新。这些设计思想不仅体现在技术实现上,也反映在社区文化和开发模式中。

可扩展性

PostgreSQL从一开始就被设计为高度可扩展的数据库系统。这种可扩展性体现在多个层面:
  • 数据类型扩展:用户可以定义自定义数据类型,包括复合类型、枚举类型、范围类型等
  • 函数扩展:支持多种编程语言编写函数,如PL/pgSQL、PL/Python、PL/Perl等
  • 索引扩展:支持自定义索引方法,如GiST、SP-GiST、GIN等
  • 外部数据包装器(FDW):可以访问外部数据源,如Oracle、MySQL、MongoDB等
sql
-- 创建自定义数据类型
CREATE TYPE address AS (
    street VARCHAR(100),
    city VARCHAR(50),
    zip_code VARCHAR(10)
);

-- 创建自定义函数
CREATE OR REPLACE FUNCTION calculate_tax(numeric) RETURNS numeric AS 

    \[BEGIN     RETURN $1 * 0.08; END;\]

LANGUAGE plpgsql; -- 使用扩展 CREATE EXTENSION postgis; -- 地理信息系统扩展 CREATE EXTENSION pg_stat_statements; -- 查询统计扩展

标准合规性

PostgreSQL非常重视SQL标准的合规性,尽可能遵循ANSI SQL和ISO SQL标准。这种对标准的坚持使得PostgreSQL具有良好的兼容性和可移植性。
  • SQL标准支持:支持大部分SQL:2011标准特性
  • 事务隔离级别:支持四种标准隔离级别:读未提交、读已提交、可重复读和串行化
  • 数据完整性:支持外键约束、唯一约束、检查约束等
info PostgreSQL的隔离级别实现
PostgreSQL实现了四种标准隔离级别,但有一些独特之处: 1. 读未提交(Read Uncommitted)在PostgreSQL中实际上与读已提交相同,不允许脏读 2. 可重复读(Repeatable Read)通过MVCC机制实现,实际上可以防止幻读 3. 串行化(Serializable)通过真正的串行化执行或预测性锁定技术实现

可靠性与数据完整性

PostgreSQL将数据完整性和可靠性放在首位,通过多种机制确保数据的一致性和持久性:
  • WAL机制:确保事务的持久性,即使系统崩溃也能恢复数据
  • 事务ACID特性:严格支持原子性、一致性、隔离性和持久性
  • 数据完整性约束:支持主键、外键、唯一、检查等多种约束
  • 崩溃恢复:提供完善的崩溃恢复机制,确保数据一致性

开源与社区驱动

PostgreSQL是一个真正的开源项目,由全球社区共同开发和维护。这种开源和社区驱动的模式带来了以下优势:
  • 透明性:所有开发过程公开透明,任何人都可以参与
  • 多样性:来自不同背景的贡献者带来多样化的思想和解决方案
  • 持续创新:社区驱动的开发模式促进了持续的创新和改进
  • 用户反馈:直接从用户社区获取反馈,快速响应需求

stars PostgreSQL 特性与优势

丰富的数据类型

PostgreSQL支持丰富的数据类型,不仅包括标准的关系型数据类型,还包括多种高级数据类型:
数据类型类别 具体类型 特点
基本类型 整数、浮点数、字符、日期时间等 标准SQL数据类型
几何类型 点、线、多边形、圆等 支持空间数据操作
网络地址类型 inet, cidr, macaddr等 专门用于存储网络地址
文本搜索类型 tsvector, tsquery 支持全文搜索
JSON类型 json, jsonb 支持JSON数据存储和查询
数组类型 任意类型的数组 支持数组操作和索引
范围类型 int4range, daterange等 支持范围查询
自定义类型 复合类型、枚举类型等 用户可定义自己的数据类型
sql
-- JSON类型示例
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    attributes JSONB
);

INSERT INTO products (name, attributes) VALUES 
('Laptop', '{"color": "silver", "weight": "1.5kg", "price": 999.99}'),
('Phone', '{"color": "black", "weight": "0.2kg", "price": 699.99}');

-- 查询JSON数据
SELECT name, attributes->>'color' AS color, attributes->>'price' AS price
FROM products
WHERE (attributes->>'price')::numeric > 800;

-- 数组类型示例
CREATE TABLE posts (
    id SERIAL PRIMARY KEY,
    title VARCHAR(100),
    tags TEXT[]
);

INSERT INTO posts (title, tags) VALUES 
('PostgreSQL Guide', ARRAY['database', 'postgres', 'sql']),
('Database Design', ARRAY['database', 'design']);

-- 查询数组数据
SELECT title, tags
FROM posts
WHERE 'database' = ANY(tags);

高级索引功能

PostgreSQL提供多种索引类型,支持不同场景下的高效查询:
索引类型 适用场景 特点
B-tree 等值查询、范围查询 默认索引类型,适用于大多数场景
Hash 等值查询 仅适用于等值查询,比B-tree更节省空间
GiST 地理数据、全文搜索 通用搜索树,支持多种数据类型
SP-GiST 空间分区数据 空间分区通用搜索树,适用于非平衡数据结构
GIN 多值类型(数组、JSON、全文搜索) 广义倒排索引,适用于包含多个键的值
BRIN 线性排序的大表 块范围索引,适用于按物理顺序存储的大表
sql
-- 创建不同类型的索引
-- B-tree索引
CREATE INDEX idx_products_name ON products(name);

-- GIN索引(用于JSONB)
CREATE INDEX idx_products_attributes ON products USING GIN(attributes);

-- 部分索引
CREATE INDEX idx_active_users ON users(email) WHERE is_active = true;

-- 表达式索引
CREATE INDEX idx_users_lower_email ON users(lower(email));

-- 复合索引
CREATE INDEX idx_orders_customer_date ON orders(customer_id, order_date);

并发与性能

PostgreSQL通过多种机制提供出色的并发性能和可扩展性:
  • MVCC机制:读写操作不互相阻塞,提高并发性能
  • 并行查询:支持并行顺序扫描、并行连接、并行聚合等操作
  • 表分区:支持声明式分区,提高大表的查询性能
  • JIT编译:即时编译表达式,提高复杂查询性能
  • 连接池:支持pgBouncer等连接池工具,减少连接开销
sql
-- 启用并行查询
SET max_parallel_workers_per_gather = 4;

-- 查看并行查询执行计划
EXPLAIN ANALYZE SELECT * FROM large_table WHERE condition;

-- 创建分区表
CREATE TABLE measurement (
    city_id int,
    log_date date,
    peaktemp int,
    unitsales int
) PARTITION BY RANGE (log_date);

-- 创建分区
CREATE TABLE measurement_y2023 PARTITION OF measurement
    FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');

CREATE TABLE measurement_y2024 PARTITION OF measurement
    FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');

高可用与复制

PostgreSQL提供多种高可用和复制解决方案,确保数据的安全性和可用性:
  • 流复制:基于WAL的物理复制,支持同步和异步模式
  • 逻辑复制:基于行变更的逻辑复制,支持选择性复制和跨版本复制
  • 故障转移:支持自动故障转移工具如Patroni、repmgr等
  • 负载均衡:支持读写分离和负载均衡
sql
-- 配置主库进行流复制
-- 在postgresql.conf中设置:
wal_level = replica
max_wal_senders = 3
max_replication_slots = 3

-- 在pg_hba.conf中添加复制连接:
host replication replicator 192.168.1.0/24 md5

-- 创建复制用户
CREATE USER replicator REPLICATION LOGIN PASSWORD 'password';

-- 在备库上设置恢复配置
standby_mode = on
primary_conninfo = 'host=primary_host port=5432 user=replicator password=password'

business PostgreSQL 应用场景

PostgreSQL凭借其丰富的功能和卓越的性能,适用于多种应用场景。以下是一些典型的应用场景:

企业级应用

PostgreSQL的ACID事务支持、数据完整性和可靠性使其成为企业级应用的理想选择:
  • ERP系统:处理复杂的业务逻辑和大量事务
  • CRM系统:管理客户数据和交互历史
  • 人力资源系统:管理员工信息和组织结构
  • 财务系统:处理财务数据和报表

地理信息系统(GIS)

通过PostGIS扩展,PostgreSQL成为地理信息系统领域的首选数据库:
  • 地图服务:存储和查询地理空间数据
  • 位置分析:基于地理位置的数据分析
  • 路径规划:计算最优路径和距离
  • 地理围栏:定义和检测地理边界
sql
-- 安装PostGIS扩展
CREATE EXTENSION postgis;

-- 创建包含地理数据的表
CREATE TABLE locations (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    geom GEOMETRY(Point, 4326)
);

-- 插入地理数据
INSERT INTO locations (name, geom) VALUES 
('北京', ST_GeomFromText('POINT(116.4074 39.9042)', 4326)),
('上海', ST_GeomFromText('POINT(121.4737 31.2304)', 4326));

-- 查询距离北京100公里内的位置
SELECT name, ST_Distance(geom, ST_GeomFromText('POINT(116.4074 39.9042)', 4326)) AS distance
FROM locations
WHERE ST_DWithin(geom, ST_GeomFromText('POINT(116.4074 39.9042)', 4326), 0.9);  -- 0.9度约等于100公里

数据分析与商业智能

PostgreSQL的复杂查询能力、窗口函数和可扩展性使其成为数据分析和商业智能应用的理想选择:
  • 数据仓库:存储和分析大量历史数据
  • 报表系统:生成复杂的业务报表
  • OLAP分析:多维数据分析
  • 数据挖掘:发现数据中的模式和趋势
sql
-- 窗口函数示例
SELECT 
    department_id,
    employee_id,
    salary,
    AVG(salary) OVER (PARTITION BY department_id) AS dept_avg_salary,
    salary - AVG(salary) OVER (PARTITION BY department_id) AS difference_from_avg
FROM employees;

-- 公用表表达式(CTE)示例
WITH regional_sales AS (
    SELECT region, SUM(amount) AS total_sales
    FROM orders
    GROUP BY region
), top_regions AS (
    SELECT region
    FROM regional_sales
    WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
)
SELECT region, product, SUM(quantity) AS product_units
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;

Web应用

PostgreSQL的高性能、可靠性和丰富的数据类型使其成为各种Web应用的后端数据库:
  • 内容管理系统:存储和管理网站内容
  • 电子商务平台:处理产品、订单和支付数据
  • 社交网络:管理用户关系和互动数据
  • SaaS应用:多租户数据隔离和管理

物联网(IoT)与时序数据

通过扩展如TimescaleDB,PostgreSQL可以高效处理物联网和时序数据:
  • 传感器数据:存储和分析大量传感器读数
  • 监控系统:实时监控和告警
  • 设备追踪:记录和分析设备状态
  • 预测性维护:基于历史数据预测设备故障

summarize 总结

PostgreSQL作为一个功能强大、可靠且高度可扩展的开源数据库系统,凭借其先进的架构设计、丰富的特性和活跃的社区支持,已成为企业和开发者的首选数据库之一。无论是传统的关系型数据管理,还是现代的地理信息系统、数据分析和物联网应用,PostgreSQL都能提供出色的解决方案。
随着PostgreSQL 18等新版本的发布,PostgreSQL在性能、功能和易用性方面不断提升,进一步巩固了其在数据库领域的领先地位。对于寻求可靠、高性能且具有长期发展潜力的数据库解决方案的组织和个人来说,PostgreSQL无疑是一个值得考虑的选择。

发表评论

人生梦想 - 关注前沿的计算机技术 acejoy.com 🐾 步子哥の博客 🐾 背多分论坛 🐾 知差(chai)网 🐾 DeepracticeX 社区 🐾 老薛主机 🐾 智柴论坛 🐾