PostgreSQL 简介
🎯 什么是 PostgreSQL
PostgreSQL 是一个功能强大的开源对象关系型数据库管理系统(ORDBMS),以其高扩展性和对 SQL 标准的高度兼容性而著称。自 1996 年发布以来,PostgreSQL 在全球范围内被广泛应用于各种规模的应用程序中。
📈 发展历程
- 1986 年:加州大学伯克利分校启动 POSTGRES 项目
- 1996 年:项目更名为 PostgreSQL,正式支持 SQL
- 1997 年:发布 PostgreSQL 6.0,引入多列索引、序列等特性
- 2000 年代:持续发展,引入 WAL、表空间、时间点恢复等功能
- 2010 年代:JSON 支持、并行查询、逻辑复制等重大更新
- 2020 年代:分区表改进、JIT 编译、增量备份等性能优化
🌟 为什么选择 PostgreSQL
- 🔒 数据完整性:严格的 ACID 事务支持
- 🚀 高性能:多版本并发控制(MVCC)技术
- 🔧 高扩展性:丰富的扩展和自定义功能
- 📊 丰富的数据类型:支持 JSON、数组、地理空间等
- 🌍 标准兼容:高度符合 SQL 标准
- 💰 开源免费:无许可证费用,社区活跃
核心特性与优势
🔐 ACID 事务支持
PostgreSQL 完全支持事务的 ACID 特性:
- 原子性(Atomicity):事务要么全部成功,要么全部失败
- 一致性(Consistency):数据库始终保持一致状态
- 隔离性(Isolation):并发事务相互隔离
- 持久性(Durability):已提交的事务永久保存
🔄 多版本并发控制(MVCC)
MVCC 是 PostgreSQL 的核心技术之一:
-- 示例:MVCC 工作原理 BEGIN; UPDATE users SET name = '新名字' WHERE id = 1; -- 此时其他事务仍能看到旧数据 COMMIT; -- 提交后,新数据对所有事务可见
📦 丰富的数据类型
PostgreSQL 支持超过 40 种数据类型:
| 类型分类 | 具体类型 | 示例 |
|---|---|---|
| 数值类型 | INTEGER, BIGINT, DECIMAL | 123, 1234567890123456789 |
| 字符类型 | VARCHAR, TEXT, CHAR | 'Hello World' |
| 日期时间 | TIMESTAMP, DATE, TIME | '2025-10-03 10:30:00' |
| 布尔类型 | BOOLEAN | true, false |
| 数组类型 | INTEGER\[\], TEXT\[\] | {1,2,3}, {'a','b','c'} |
| JSON 类型 | JSON, JSONB | '{"name": "张三"}' |
| 地理空间 | POINT, POLYGON | POINT(116.3974, 39.9093) |
🔧 扩展性
PostgreSQL 允许用户:
- 创建自定义数据类型
- 定义新的操作符
- 编写自定义函数
- 开发新的索引方法
- 实现存储过程和触发器
系统架构
PostgreSQL 采用客户端/服务器架构,主要组件包括:
🏗️ 核心组件
- Postmaster 进程:主进程,负责启动和监控
- Backend 进程:处理客户端连接和查询
- WAL Writer:写前日志写入器
- Checkpointer:检查点进程
- Background Writer:后台写入器
- Autovacuum:自动清理进程
📊 内存结构
- Shared Buffers:共享缓冲区
- WAL Buffers:WAL 缓冲区
- Work Memory:工作内存
- Maintenance Work Memory:维护工作内存
🏛️ PostgreSQL 架构图
PostgreSQL 服务器
客户端应用
连接层
查询处理层
存储层
后台进程
存储系统
数据文件
WAL 文件
配置文件
WAL Writer
Checkpointer
Background Writer
Autovacuum
Buffer Manager
WAL Manager
Storage Manager
查询解析器
查询优化器
执行器
Postmaster 进程
Backend 进程 1
Backend 进程 2
Backend 进程 N
Web 应用
桌面应用
移动应用
🔄 MVCC 工作原理图
事务 1事务 2数据库事务 1 开始事务 2 开始事务 1 提交事务 2 再次查询BEGINUPDATE users SET name='新名字' WHERE id=1BEGINSELECT name FROM users WHERE id=1返回旧值 '旧名字'COMMITSELECT name FROM users WHERE id=1返回新值 '新名字'COMMIT事务 1事务 2数据库
数据类型详解
🔢 数值类型
-- 整数类型 CREATE TABLE numbers ( id SERIAL PRIMARY KEY, -- 自增整数 small_num SMALLINT, -- 2 字节整数 (-32768 到 32767) normal_num INTEGER, -- 4 字节整数 big_num BIGINT, -- 8 字节整数 decimal_num DECIMAL(10,2), -- 精确小数 float_num REAL, -- 单精度浮点数 double_num DOUBLE PRECISION -- 双精度浮点数 );
📝 字符类型
-- 字符类型示例 CREATE TABLE text_examples ( id SERIAL PRIMARY KEY, fixed_char CHAR(10), -- 固定长度字符 var_char VARCHAR(255), -- 可变长度字符 unlimited_text TEXT, -- 无限制文本 name CITEXT -- 大小写不敏感文本 ); -- 插入数据 INSERT INTO text_examples (fixed_char, var_char, unlimited_text, name) VALUES ('Hello', 'World', 'This is a long text...', 'JOHN DOE');
📅 日期时间类型
-- 日期时间类型 CREATE TABLE datetime_examples ( id SERIAL PRIMARY KEY, birth_date DATE, -- 日期 work_time TIME, -- 时间 created_at TIMESTAMP, -- 时间戳 updated_at TIMESTAMPTZ, -- 带时区的时间戳 duration INTERVAL -- 时间间隔 ); -- 插入数据 INSERT INTO datetime_examples (birth_date, work_time, created_at, updated_at, duration) VALUES ('1990-01-01', '09:30:00', '2025-10-03 10:30:00', '2025-10-03 10:30:00+08', '1 day 2 hours 30 minutes');
📋 数组类型
-- 数组类型示例 CREATE TABLE array_examples ( id SERIAL PRIMARY KEY, numbers INTEGER[], -- 整数数组 names TEXT[], -- 文本数组 matrix INTEGER[][] -- 二维数组 ); -- 插入数组数据 INSERT INTO array_examples (numbers, names, matrix) VALUES ('{1,2,3,4,5}', '{"张三","李四","王五"}', '{``{1,2},{3,4}}'); -- 查询数组 SELECT * FROM array_examples WHERE 2 = ANY(numbers); SELECT names[1] FROM array_examples; -- 获取第一个名字
📄 JSON 类型
-- JSON 类型示例 CREATE TABLE json_examples ( id SERIAL PRIMARY KEY, user_info JSON, -- JSON 类型 user_data JSONB -- 二进制 JSON 类型 ); -- 插入 JSON 数据 INSERT INTO json_examples (user_info, user_data) VALUES ('{"name": "张三", "age": 25, "city": "北京"}', '{"name": "李四", "age": 30, "hobbies": ["读书", "游泳"]}'); -- JSON 查询 SELECT user_data->>'name' FROM json_examples; -- 获取名字 SELECT user_data->'hobbies' FROM json_examples; -- 获取爱好数组 SELECT * FROM json_examples WHERE user_data @> '{"age": 30}'; -- 查询年龄为 30 的用户
索引技术
🔍 索引类型
PostgreSQL 支持多种索引类型:
1. B-Tree 索引(默认)
-- 创建 B-Tree 索引 CREATE INDEX idx_users_email ON users(email); CREATE INDEX idx_users_name_age ON users(name, age); -- 复合索引
2. Hash 索引
-- 创建 Hash 索引(仅支持等值查询) CREATE INDEX idx_users_id_hash ON users USING hash(id);
3. GIN 索引(通用倒排索引)
-- 用于数组和 JSON 数据 CREATE INDEX idx_users_tags_gin ON users USING gin(tags); CREATE INDEX idx_users_data_gin ON users USING gin(user_data);
4. GiST 索引(通用搜索树)
-- 用于地理空间数据 CREATE INDEX idx_locations_gist ON locations USING gist(coordinates);
5. BRIN 索引(块范围索引)
-- 用于大表的范围查询 CREATE INDEX idx_logs_brin ON logs USING brin(created_at);
🔍 索引类型对比图
适用场景
索引类型
常规查询
排序
范围查询
精确匹配
等值查询
全文搜索
数组查询
JSON 查询
地理查询
空间索引
时间序列
大表扫描
B-Tree 索引
默认索引
范围查询
Hash 索引
等值查询
内存友好
GIN 索引
倒排索引
数组/JSON
GiST 索引
搜索树
地理空间
BRIN 索引
块范围
大表优化
事务与并发控制
🔄 事务隔离级别
PostgreSQL 支持四种事务隔离级别:
-- 设置事务隔离级别 BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; -- 执行操作 COMMIT; -- 隔离级别说明 -- READ UNCOMMITTED: 读取未提交数据(PostgreSQL 中实际为 READ COMMITTED) -- READ COMMITTED: 读取已提交数据(默认) -- REPEATABLE READ: 可重复读取 -- SERIALIZABLE: 串行化
📊 事务隔离级别对比
事务隔离级别
READ UNCOMMITTED
读取未提交
READ COMMITTED
读取已提交
默认级别
REPEATABLE READ
可重复读取
SERIALIZABLE
串行化
脏读 YES
不可重复读 YES
幻读 YES
脏读 NO
不可重复读 YES
幻读 YES
脏读 NO
不可重复读 NO
幻读 YES
脏读 NO
不可重复读 NO
幻读 NO
🔒 锁机制
-- 表级锁 LOCK TABLE users IN SHARE MODE; -- 共享锁 LOCK TABLE users IN EXCLUSIVE MODE; -- 排他锁 -- 行级锁(自动) UPDATE users SET name = '新名字' WHERE id = 1; -- 自动加行级排他锁 -- 查看锁信息 SELECT * FROM pg_locks WHERE relation = 'users'::regclass;
⚡ MVCC 示例
-- 会话 1 BEGIN; UPDATE users SET balance = balance - 100 WHERE id = 1; -- 此时事务未提交 -- 会话 2(同时执行) SELECT balance FROM users WHERE id = 1; -- 仍看到旧值 -- 会话 1 COMMIT; -- 提交后,会话 2 的下次查询将看到新值
安装与配置
💻 Windows 安装
1. 下载安装包
访问 PostgreSQL 官网 下载最新版本。
2. 安装步骤
- 运行安装程序
- 选择安装路径
- 设置超级用户密码
- 选择端口(默认 5432)
- 选择语言环境
3. 验证安装
# 检查 PostgreSQL 服务状态 sc query postgresql-x64-16 # 连接到数据库 psql -U postgres -h localhost -p 5432
🐧 Linux 安装
Ubuntu/Debian
# 更新包列表 sudo apt update # 安装 PostgreSQL sudo apt install postgresql postgresql-contrib # 启动服务 sudo systemctl start postgresql sudo systemctl enable postgresql # 切换到 postgres 用户 sudo -u postgres psql
CentOS/RHEL
# 安装 PostgreSQL sudo yum install postgresql-server postgresql-contrib # 初始化数据库 sudo postgresql-setup initdb # 启动服务 sudo systemctl start postgresql sudo systemctl enable postgresql
⚙️ 基本配置
postgresql.conf 配置
# 连接设置 listen_addresses = '*' # 监听所有地址 port = 5432 # 端口号 max_connections = 100 # 最大连接数 # 内存设置 shared_buffers = 256MB # 共享缓冲区 work_mem = 4MB # 工作内存 maintenance_work_mem = 64MB # 维护工作内存 # 日志设置 log_destination = 'stderr' # 日志目标 logging_collector = on # 启用日志收集 log_directory = 'log' # 日志目录 log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' log_min_duration_statement = 1000 # 记录慢查询(毫秒) # 性能设置 random_page_cost = 1.1 # 随机页面成本 effective_cache_size = 1GB # 有效缓存大小
pg_hba.conf 配置
# 本地连接 local all all trust # IPv4 本地连接 host all all 127.0.0.1/32 md5 # IPv6 本地连接 host all all ::1/128 md5 # 网络连接 host all all 0.0.0.0/0 md5
性能优化
📈 查询优化
1. 使用 EXPLAIN 分析查询
-- 基本查询分析 EXPLAIN SELECT * FROM users WHERE email = 'test@example.com'; -- 详细分析(包含实际执行时间) EXPLAIN (ANALYZE, BUFFERS, VERBOSE) SELECT u.name, p.title FROM users u JOIN posts p ON u.id = p.user_id WHERE u.active = true;