Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← Web 开发 / Web Development

数据库与数据访问 / Databases & Data Access

1. 数据库全景学习路线 / A Complete Database Learning Path

2. MySQL 实战——互联网标配关系型数据库 / Practical MySQL for Internet Applications

3. PostgreSQL 深度——功能最全的开源 RDBMS / PostgreSQL as a Feature-Rich Open-Source RDBMS

4. SQLite 嵌入式——零配置的极致轻量 / SQLite as a Lightweight Embedded Database

5. MongoDB 文档型数据库——灵活结构的代表 / MongoDB and Flexible Document Data Models

6. Redis 全方位——不只是缓存 / Redis Beyond Caching

7. 嵌入式 KV 数据库——基础设施层的隐形支柱 / Embedded Key-Value Databases for Infrastructure

8. NewSQL 分布式数据库——规模化关系型数据 / Distributed SQL for Relational Data at Scale

9. 向量数据库——AI 时代的语义基础设施 / Vector Databases as Semantic Infrastructure for AI

10. OLAP 列式数据库——极速分析引擎 / Columnar OLAP Databases for Fast Analytics

11. 时序数据库——时间线数据的专业存储 / Time-Series Databases for Timeline Data

12. 数据库选型决策指南——从理论到实践 / A Practical Guide to Database Selection

13. ORM 与 Prisma 完全指南 / A Complete Guide to ORMs and Prisma

本页目录

PostgreSQL 深度——功能最全的开源 RDBMS / PostgreSQL as a Feature-Rich Open-Source RDBMS ​

📅 创建时间:2026-05-08 🏷️ 标签:#PostgreSQL #JSONB #pgvector #PostGIS #窗口函数 #CTE 📚 前置知识:[[00-db-overview]] [[01-mysql]](了解索引和事务基础) 📚 相关知识:[[08-vector-database]](pgvector)、[[07-distributed-sql]](CockroachDB)


PostgreSQL 定位速览 ​

┌─────────────────────────────────────────────────────────────┐
│                PostgreSQL 在数据库版图中的位置                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  GitHub Stars: 15K+,Stack Overflow 连续多年"最受喜爱数据库"  │
│  定位:      功能最丰富、最"正经"的开源关系型数据库            │
│  核心优势:  几乎涵盖所有 SQL 标准的扩展功能                   │
│  适用场景:  复杂查询、AI 向量、地理空间、全文本搜索、ETL      │
│                                                             │
│  一句话总结:                                               │
│  如果 MySQL 能做的事 PostgreSQL 都能做,                     │
│  那么 PostgreSQL 能做的事,MySQL 往往做不了。               │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14

第1部分:PostgreSQL vs MySQL——核心差异 ​

┌─────────────────────────────────────────────────────────────┐
│                    PostgreSQL vs MySQL 核心差异                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  │ 维度           │ PostgreSQL              │ MySQL          │
│  ├────────────────┼────────────────────────┼────────────────┤
│  │ SQL 标准遵循    │ 近乎完整(CTE/窗口函数) │ 部分遵循       │
│  │ MVCC           │ 真正的 MVCC             │ 改进版         │
│  │ 索引类型       │ 8+ 种(B-tree/Hash/     │ 5 种           │
│  │                │ GiST/SP-GiST/GIN/Brin)│                │
│  │ JSON 支持       │ JSONB(独立类型+索引)   │ JSON(文本+索引)│
│  │ JSONB vs JSON  │ JSONB: 二进制+可索引    │ JSON: 文本解析  │
│  │                │                       │                │
│  │ 扩展性         │ CREATE EXTENSION       │ 插件有限       │
│  │                │ (pgvector/PostGIS/...) │                │
│  │ 分区表         │ 声明式分区(原生)       │ 分区表(有限) │
│  │ 并行查询       │ 真正的并行(多核利用)   │ 有限并行       │
│  │ 复制方案       │ 逻辑复制 + 流复制        │ binlog 复制    │
│  │ 许可           │ PostgreSQL License     │ GPL v2         │
│  │                │ (BSD 风格,无传染性)   │ (GPL 传染)   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

第2部分:高级 SQL 特性 ​

2.1 CTE(公用表表达式) ​

CTE 让复杂查询可读性大幅提升:

sql
-- 递归 CTE:查询组织架构
WITH RECURSIVE org_tree AS (
    -- 基础:CEO
    SELECT id, name, manager_id, 1 as level
    FROM employees
    WHERE manager_id IS NULL

    UNION ALL

    -- 递归:下属
    SELECT e.id, e.name, e.manager_id, ot.level + 1
    FROM employees e
    JOIN org_tree ot ON e.manager_id = ot.id
)
SELECT * FROM org_tree ORDER BY level, name;

-- 普通 CTE:让查询更清晰
WITH active_users AS (
    SELECT id, name, created_at
    FROM users
    WHERE status = 'active'
),
user_orders AS (
    SELECT user_id, COUNT(*) as order_count, SUM(amount) as total
    FROM orders
    GROUP BY user_id
)
SELECT u.name, u.created_at, o.order_count, o.total
FROM active_users u
JOIN user_orders o ON u.id = o.user_id
WHERE o.order_count > 5
ORDER BY o.total DESC;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

2.2 窗口函数 ​

窗口函数在分组内进行有序计算,是 SQL 的高级特性:

sql
-- 窗口函数基础
SELECT
    product_name,
    category,
    price,
    -- 窗口函数:分组内排名
    RANK() OVER (PARTITION BY category ORDER BY price DESC) as rank_in_category,
    -- 窗口函数:分组内前一个价格(环比)
    LAG(price, 1) OVER (PARTITION BY category ORDER BY sale_date) as prev_price,
    -- 窗口函数:分组累计销售额
    SUM(amount) OVER (PARTITION BY category ORDER BY sale_date) as running_total,
    -- 窗口函数:分组平均值
    AVG(amount) OVER (PARTITION BY category) as category_avg,
    -- 窗口函数:当前行在分组中的位置百分比
    PERCENT_RANK() OVER (PARTITION BY category ORDER BY amount) as pct_rank
FROM sales;

-- 实战:查询每个用户订单总额,以及占其所在城市的比例
SELECT
    u.id,
    u.city,
    u.total_spent,
    city_totals.city_total,
    ROUND(u.total_spent * 100.0 / city_totals.city_total, 2) as pct_of_city
FROM (
    SELECT id, city, SUM(order_amount) as total_spent
    FROM users u JOIN orders o ON u.id = o.user_id
    GROUP BY id, city
) u
JOIN (
    SELECT city, SUM(order_amount) as city_total
    FROM users u JOIN orders o ON u.id = o.user_id
    GROUP BY city
) city_totals ON u.city = city_totals.city;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

2.3 UPSERT——冲突处理 ​

sql
-- PostgreSQL UPSERT(INSERT ... ON CONFLICT)
INSERT INTO user_stats (user_id, login_count, last_login)
VALUES (1001, 1, NOW())
ON CONFLICT (user_id)  -- 冲突键
DO UPDATE SET
    login_count = user_stats.login_count + 1,
    last_login = EXCLUDED.last_login;

-- 完整版本:带 WHERE 条件
INSERT INTO products (id, name, stock, updated_at)
VALUES (1, 'Widget', 100, NOW())
ON CONFLICT (id) DO UPDATE
SET stock = products.stock + EXCLUDED.stock,
    updated_at = EXCLUDED.updated_at
WHERE products.stock < 1000;  -- 只在库存未满时增加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

第3部分:JSONB——文档与关系型的融合 ​

PostgreSQL 的 JSONB 是它的杀手级特性之一:

┌─────────────────────────────────────────────────────────────┐
│                    JSONB 的优势                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  MySQL JSON:   存储为 TEXT,查询时解析,速度慢             │
│  PostgreSQL JSONB:存储为二进制,有独立类型,可建索引       │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  CREATE INDEX idx_user_meta ON users               │   │
│  │    USING GIN (metadata jsonb_path_ops);            │   │
│  │                                                     │   │
│  │  -- 查询任意嵌套字段,带索引                         │   │
│  │  SELECT * FROM users                                │   │
│  │  WHERE metadata @> '{"preferences": {"theme": "dark"}}';│   │
│  │                                                     │   │
│  │  -- GIN 索引支持的查询操作符:                      │   │
│  │  @>  包含(Contains)                               │   │
│  │  ?   键存在(Key exists)                           │   │
│  │  ?&  所有键存在                                     │   │
│  │  ?|  任一键存在                                     │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
sql
-- JSONB 实战
-- 1. 存储用户配置(灵活字段)
CREATE TABLE user_configs (
    id SERIAL PRIMARY KEY,
    user_id INT REFERENCES users(id),
    config JSONB DEFAULT '{}',
    created_at TIMESTAMP DEFAULT NOW()
);

INSERT INTO user_configs (user_id, config) VALUES (1, '{
    "theme": "dark",
    "notifications": {
        "email": true,
        "push": false
    },
    "language": "zh-CN"
}');

-- 2. 查询:提取 JSON 字段
SELECT
    user_id,
    config->>'theme' as theme,          -- 获取字符串
    config->'notifications'->>'email' as email_notif,  -- 嵌套
    config->'notifications'->>'push' as push_notif,
    #config->'notifications' as notif_count  -- 数组长度
FROM user_configs;

-- 3. 更新 JSON
UPDATE user_configs
SET config = jsonb_set(config, '{notifications, email}', 'false')
WHERE user_id = 1;

UPDATE user_configs
SET config = config || '{"timezone": "Asia/Shanghai"}'
WHERE user_id = 1;

-- 4. 全文搜索 JSONB
SELECT * FROM user_configs
WHERE config @@ '$.notifications.email == true';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

第4部分:pgvector——PostgreSQL 原生向量检索 ​

这是 AI 时代 PostgreSQL 最重要的扩展:

┌─────────────────────────────────────────────────────────────┐
│                    pgvector 向量检索                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  pgvector 让 PostgreSQL 直接支持向量存储和相似度搜索,       │
│  无需额外的向量数据库。                                     │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  -- 安装扩展                                          │   │
│  │  CREATE EXTENSION IF NOT EXISTS vector;             │   │
│  │                                                     │   │
│  │  -- 定义向量列(1536 维 = OpenAI embedding 维度)     │   │
│  │  CREATE TABLE documents (                            │   │
│  │    id SERIAL PRIMARY KEY,                           │   │
│  │    content TEXT,                                     │   │
│  │    embedding VECTOR(1536)                           │   │
│  │  );                                                  │   │
│  │                                                     │   │
│  │  -- 创建 HNSW 索引(近似最近邻)                     │   │
│  │  CREATE INDEX ON documents                           │   │
│  │    USING hnsw (embedding vector_cosine_ops);        │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  支持的相似度度量:                                         │
│  • cosine_distance(余弦距离)← 最常用                      │
│  • euclidean_distance(欧氏距离)                          │
│  • inner_product(内积)                                   │
│                                                             │
│  pgvector vs 专用向量数据库:                              │
│  • pgvector: <100万向量、已有 PG 表结构、需要事务支持      │
│  • Milvus: >100万向量、需要独立运维、超高 QPS               │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
sql
-- pgvector 实战:RAG 语义检索
-- 1. 插入带 embedding 的文档
INSERT INTO documents (content, embedding)
VALUES (
    'PostgreSQL 是一个功能强大的开源关系型数据库',
    '[0.123, -0.456, ...]'::vector  -- 1536 维
);

-- 2. 语义搜索(查询先 embedding)
SELECT id, content,
    -- 计算余弦距离(越小越相似)
    1 - (embedding <=> '[0.124, -0.455, ...]'::vector) as similarity
FROM documents
ORDER BY embedding <=> '[0.124, -0.455, ...]'::vector
LIMIT 5;

-- 3. 过滤 + 向量混合检索
SELECT id, content,
    1 - (embedding <=> query_embedding) as similarity
FROM documents, (
    SELECT '[0.124, -0.455, ...]'::vector as query_embedding
) q
WHERE created_at > '2026-01-01'  -- 传统过滤条件
ORDER BY embedding <=> query_embedding
LIMIT 5;

-- 4. pgvectorscale(TimescaleDB 出品,性能提升 10x)
-- 在 pgvector 基础上支持 StreamingDiskANN 索引
-- 适合 billion 级别的向量数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

第5部分:PostGIS 地理空间 ​

sql
-- 启用 PostGIS
CREATE EXTENSION postgis;

-- 存储地理位置
CREATE TABLE stores (
    id SERIAL PRIMARY KEY,
    name TEXT,
    location GEOGRAPHY(POINT, 4326)  -- POINT + WGS84 坐标系
);

INSERT INTO stores (name, location) VALUES
    ('三里屯店', ST_SetSRID(ST_MakePoint(116.45, 39.93), 4326)),
    ('国贸店',   ST_SetSRID(ST_MakePoint(116.46, 39.91), 4326));

-- 查询:附近门店(半径 5 公里内)
SELECT id, name,
    ST_Distance(
        location,
        ST_SetSRID(ST_MakePoint(116.45, 39.93), 4326)::geography
    ) / 1000 as distance_km
FROM stores
WHERE ST_DWithin(
    location,
    ST_SetSRID(ST_MakePoint(116.45, 39.93), 4326)::geography,
    5000  -- 5 公里
)
ORDER BY location <-> ST_SetSRID(ST_MakePoint(116.45, 39.93), 4326);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

第6部分:分区表与并行查询 ​

sql
-- 声明式分区(PostgreSQL 10+)
CREATE TABLE logs (
    id BIGSERIAL,
    created_at TIMESTAMP NOT NULL,
    level TEXT,
    message TEXT
) PARTITION BY RANGE (created_at);

-- 按月分区
CREATE TABLE logs_2026_01 PARTITION OF logs
    FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');
CREATE TABLE logs_2026_02 PARTITION OF logs
    FOR VALUES FROM ('2026-02-01') TO ('2026-03-01');

-- 查询自动路由到正确分区
INSERT INTO logs (created_at, level, message) VALUES
    ('2026-01-15', 'INFO', 'user login');

-- EXPLAIN 显示分区裁剪(Partition Pruning)
EXPLAIN SELECT * FROM logs WHERE created_at = '2026-01-15';
-- Output: -> Parallel Seq Scan on logs_2026_01  (cost=...)
--         Filter: (created_at = '2026-01-15'::date)
--         ->  Partitioned index scan using logs on logs
--             Partition key constraints: (...)

-- 并行查询示例(利用多核)
SET max_parallel_workers_per_gather = 4;
EXPLAIN SELECT status, COUNT(*) FROM orders GROUP BY status;
-- Output: Finalize GroupAggregate  (cost=...)
--         -> Gather Motion  (cost=...)
--             -> Partial GroupAggregate
--                 -> Parallel Seq Scan on orders
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

第7部分:FDW 外部表 ​

PostgreSQL 的 FDW(Foreign Data Wrapper)让它可以查询外部数据源:

sql
-- 1. postgres_fdw:查询另一个 PostgreSQL
CREATE EXTENSION postgres_fdw;

CREATE SERVER remote_db FOREIGN DATA WRAPPER postgres_fdw
    OPTIONS (host '192.168.1.100', port '5432', dbname 'analytics');

CREATE USER MAPPING FOR current_user SERVER remote_db
    OPTIONS (user 'readonly_user', password 'secret');

CREATE FOREIGN TABLE remote_orders (...) SERVER remote_db;

-- 现在可以像本地表一样查询远程数据
SELECT * FROM remote_orders WHERE created_at > '2026-01-01';

-- 2. mysql_fdw:查询 MySQL
CREATE EXTENSION mysql_fdw;
CREATE SERVER mysql_server FOREIGN DATA WRAPPER mysql_fdw
    OPTIONS (host '192.168.1.101');
CREATE FOREIGN TABLE mysql_users (...) SERVER mysql_server
    OPTIONS (dbname 'webapp', table_name 'users');

-- 3. 实战:跨数据库 JOIN
SELECT u.name, o.total
FROM mysql_users u
JOIN remote_orders o ON u.id = o.user_id
WHERE o.created_at > '2026-01-01';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

第8部分:PostgreSQL 在 LLM/Agent 中的核心地位 ​

┌─────────────────────────────────────────────────────────────┐
│              PostgreSQL 在 AI 应用中的核心角色                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  PostgreSQL + pgvector = 一站式 AI 数据平台                 │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                                                     │   │
│  │  PostgreSQL(主数据库)                              │   │
│  │  ┌─────────────────────────────────────────────┐  │   │
│  │  │  messages (JSONB)     → 聊天记录            │  │   │
│  │  │  embeddings (vector)  → 向量嵌入    [pgvector]│  │   │
│  │  │  user_memories (JSONB)→ 用户记忆    [pgvector]│  │   │
│  │  │  agents (JSONB)        → Agent 配置          │  │   │
│  │  │  sessions              → 会话管理              │  │   │
│  │  │  files                 → 文件元数据            │  │   │
│  │  └─────────────────────────────────────────────┘  │   │
│  │                                                     │   │
│  │  ┌─────────────────────────────────────────────┐  │   │
│  │  │  RAG 管道(同一数据库内完成)                │  │   │
│  │  │  文档 → chunk → embedding → vector search  │  │   │
│  │  │  → 检索结果 + LLM → 生成回答                │  │   │
│  │  └─────────────────────────────────────────────┘  │   │
│  │                                                     │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  LobeChat 就使用 PostgreSQL + PGVector 作为主力数据库,     │
│  一套架构支撑:消息存储 + RAG 向量 + 用户记忆 + 文件元数据  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

学习状态:🟡 开始学习

最后更新于:

Pager
上一篇2. MySQL 实战——互联网标配关系型数据库 / Practical MySQL for Internet Applications
下一篇4. SQLite 嵌入式——零配置的极致轻量 / SQLite as a Lightweight Embedded Database

持续记录,持续成长

Copyright © Tidenflow