别再用MySQL了,AI时代这个数据库更香!

前言

最近帮几个刚入行的朋友做技术指导,发现一个普遍现象:很多人从大学学完MySQL之后,就再也没碰过别的数据库了。

到了工作中,遇到一些复杂业务场景,用MySQL去硬撑,搞得焦头烂额。

说实话,PostgreSQL这几年在企业级应用中的普及速度非常快。

2026年DB-Engines排名显示,PostgreSQL稳坐全球第四大数据库的宝座,仅次于Oracle、MySQL和SQL Server。

今天,我就用一篇文章跟大家一起聊聊PostgreSQL,希望对你会有所帮助。

更多项目实战在我的技术网站:susan.net.cn/project

一、先说一个扎心的事实

有些小伙伴在工作中可能会说:"我用MySQL用了好几年了,感觉也挺好的啊,为什么要学PostgreSQL?"

我举个简单的例子:假如你的电商系统需要查询"2024年每个季度销售额排名前3的商品",用MySQL写这个SQL起码20行起步,各种嵌套子查询、窗口函数疯狂套娃。

而PostgreSQL原生就支持RANK()窗口函数,10行代码轻松搞定。

这不叫花里胡哨,这叫生产力。

数据库的选型,决定着你未来无数个加班的夜晚是不是真的在"用代码解决问题",还是在"跟数据库做斗争"。

而且,国内外很多大厂都已经在从MySQL向PostgreSQL迁移了。

Apple、Instagram、Uber、Reddit,甚至阿里巴巴的部分业务线,都在逐步拥抱PostgreSQL。

这背后是有原因的------简单来说,MySQL适合80%的普通场景,而PostgreSQL适合剩下那20%复杂至极、对数据一致性要求极高的"硬骨头"。

二、PostgreSQL到底是什么?

PostgreSQL是一个功能强大的开源关系型数据库管理系统,它起源于1986年加州大学伯克利分校的POSTGRES项目。

经过近40年的发展,它已经成长为全球最先进的开源数据库之一。

它的核心特性有这么几个:

  • 完全开源:遵循PostgreSQL许可证,可以自由使用、修改和分发。
  • 高度可扩展:支持自定义数据类型、函数、操作符和索引方法。
  • 标准兼容性强:对SQL:2023标准的兼容度超过90%,完整支持窗口函数、公共表表达式(CTE)、全文搜索等高级SQL特性。
  • 多版本并发控制(MVCC) :读写互不阻塞,完美解决了高并发场景下的锁争用问题。
  • 丰富的扩展生态:提供PostGIS(地理信息系统)、pgvector(向量检索)、TimescaleDB(时序数据)等行业级扩展。

PostgreSQL和MySQL两者最根本的差异,我用一张图帮你理清楚:

简单来说,一个擅长"全都要",什么都能干;另一个擅长"一招鲜",在特定场景下做到极致。

三、环境搭建

咱们先把环境弄起来。

PostgreSQL可以在Linux、Windows、macOS等各种操作系统上运行。

生产环境建议内存至少8GB以上。

3.1 Windows用户

对于Windows新手,推荐使用官方图形化安装包。

步骤如下:

  1. 访问postgresql.org/download,下载Windows安装包
  2. 双击运行,一路Next
  3. 设置安装路径(默认C:\Program Files\PostgreSQL\16)
  4. 设置超级用户(postgres)密码------切记记住这个密码!
  5. 设置端口(默认5432,一般不改)
  6. 选择区域,建议选Chinese (Simplified)或English_United States
  7. 安装完成后勾选Launch Stack Builder可以跳过
  8. 打开CMD或PowerShell,输入psql -U postgres,输入密码,看到postgres=#提示符即为成功

3.2 macOS用户

macOS推荐使用Homebrew安装:

bash 复制代码
# 安装PostgreSQL
brew install postgresql

# 启动服务
brew services start postgresql

# 连接数据库
psql postgres

如果不习惯用命令行,也可以去官网下载.dmg安装包,拖拽到Applications即可。

3.3 Linux用户(Ubuntu/Debian)

Ubuntu用户推荐从官方仓库安装,确保版本最新:

bash 复制代码
# 添加官方仓库
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
# 更新并安装
sudo apt update
sudo apt install postgresql postgresql-contrib
# 启动服务
sudo systemctl start postgresql
# 切换到postgres用户
sudo -i -u postgres
psql

3.4 安装验证

无论哪个系统,安装完成后可以用下面这个命令快速验证:

sql 复制代码
SELECT version();

看到类似"PostgreSQL 16.x"的输出,恭喜你,安装成功了!

四、基础SQL全掌握

4.1 数据库基本操作

sql 复制代码
-- 创建数据库
CREATE DATABASE mydb;

-- 查看所有数据库
\l

-- 切换到指定数据库
\c mydb

-- 创建用户并授权
CREATE USER myuser WITH PASSWORD 'mypass';
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;

-- 删除数据库(生产环境慎用)
DROP DATABASE mydb;

4.2 数据类型详解

PostgreSQL支持的数据类型非常丰富,远超MySQL:

类型分类 具体类型 说明
数值类型 INTEGER、BIGINT、NUMERIC(precision, scale)、DOUBLE PRECISION NUMERIC用于精确小数,适合金额
字符串类型 VARCHAR(n)、TEXT、CHAR(n) TEXT无长度限制
日期时间 DATE、TIME、TIMESTAMP、TIMESTAMPTZ、INTERVAL TIMESTAMPTZ带时区
布尔类型 BOOLEAN true/false
JSON类型 JSON、JSONB JSONB是二进制格式,支持索引
数组类型 INTEGER\[\]、TEXT\[\] 原生数组支持
网络地址 INET、CIDR、MACADDR IP地址处理

4.3 创建表和约束

sql 复制代码
-- 创建商品表
CREATE TABLE products (
    id SERIAL PRIMARY KEY,                    -- 自增主键
    name VARCHAR(200) NOT NULL,               -- 商品名,非空
    price NUMERIC(10,2) CHECK (price > 0),    -- 价格必须大于0
    stock INTEGER DEFAULT 0,                  -- 库存,默认0
    category VARCHAR(50),
    tags TEXT[],                              -- 数组类型存标签
    created_at TIMESTAMPTZ DEFAULT NOW()      -- 带时区的时间戳
);

4.4 基本的增删改查

sql 复制代码
-- 插入数据
INSERT INTO products (name, price, stock, category, tags)
VALUES ('机械键盘', 399.00, 50, '外设', ARRAY['键盘', '电竞']),
       ('无线鼠标', 129.00, 100, '外设', ARRAY['鼠标', '无线']);

-- 查询数据
SELECT * FROM products WHERE price BETWEEN 100 AND 500;

-- 更新数据
UPDATE products SET stock = stock - 1 WHERE id = 1;

-- 删除数据
DELETE FROM products WHERE stock = 0;

五、MVCC多版本并发控制

有些小伙伴在工作中可能会问:PostgreSQL和MySQL在并发性能上到底有什么本质区别?为什么说PostgreSQL更适合高并发写场景?

这就是MVCC(Multi-Version Concurrency Control)的功劳。

PostgreSQL的并发承诺非常简单:读永远不阻塞写,写永远不阻塞读

5.1 MVCC核心原理

PostgreSQL中,每个事务都会获得一个唯一的事务ID,称为XID。

MVCC的核心区别在于:MySQL通过锁机制实现,读数据时可能会被写操作阻塞;而PostgreSQL通过快照隔离实现,永远不会有读写互锁

XMIN和XMAX是两个隐藏字段,每个数据行都有。插入时写入XMIN(创建这个版本的事务ID),更新/删除时写入XMAX(删除这个版本的事务ID),通过比较XID就可以判断事务的可见性。

5.2 事务隔离级别

PostgreSQL支持四种隔离级别,默认是READ COMMITTED,同时也提供了严格的SERIALIZABLE级别:

  • READ UNCOMMITTED:实际上等同于READ COMMITTED
  • READ COMMITTED(默认):查询只能看到已提交的数据
  • REPEATABLE READ:保证在同一事务内多次查询结果一致
  • SERIALIZABLE:最高隔离级别,使用可序列化快照隔离(SSI),能真正防止幻读和写偏序异常

如果两个事务同时修改同一行,PostgreSQL会如何处理?

这在SERIALIZABLE隔离级别下会抛错误,应用层可以选择重试或者放弃。

六、PostgreSQL的索引武器库

有些小伙伴在工作中可能会遇到这样的情况:明明给字段建了索引,慢查询还是一堆。这是因为PostgreSQL的索引体系比MySQL复杂得多,也强大得多------索引类型不同,适用场景完全不同。

6.1 索引类型全家桶

MySQL主要依赖B-tree索引,而PostgreSQL提供了丰富的索引武器库:

索引类型 典型场景 关键要点
B-tree 等值与范围查询、排序 默认类型,支持= < <= > >= ORDER BY
Hash 仅等值查询 不支持范围和排序
GIN 数组、JSONB、全文搜索 倒排结构,适合"多值"查询
GiST 地理空间、全文搜索 支持多种距离查询
BRIN 大表、按时间顺序插入的数据 体积小,适合"粗粒度"范围过滤
Bloom 多列高选择性查询 位图过滤,减少组合索引数量

B-tree是默认索引类型,但也是水最深的。比如查询LIKE '%keyword%'不会走B-tree索引,这时候需要考虑GIN或全文搜索。

GIN索引实战:加速JSONB查询

PostgreSQL的JSONB类型配上GIN索引,查询性能可以提升几百倍:

sql 复制代码
-- 创建含JSONB字段的表
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    details JSONB
);

-- 插入测试数据
INSERT INTO products (details) VALUES 
('{"name": "Laptop", "specs": {"cpu": "i7", "ram": "16GB"}, "tags": ["electronics", "sale"]}'),
('{"name": "Keyboard", "specs": {"switch": "mechanical", "connection": "wired"}, "tags": ["peripherals"]}');

-- 不加索引的查询(慢)
SELECT * FROM products WHERE details -> 'specs' ->> 'cpu' = 'i7';

-- 创建GIN索引
CREATE INDEX idx_products_details ON products USING GIN (details);

-- 索引后的快速查询(快300倍)
SELECT details -> 'name' AS name, details -> 'specs' AS specs
FROM products
WHERE details @> '{"specs": {"cpu": "i7"}}';

这里的@>是JSONB包含操作符,利用GIN索引快速定位。

6.2 表达式索引和部分索引

PostgreSQL支持两种高级索引,MySQL需要复杂配置才能实现:

sql 复制代码
-- 表达式索引:按小写邮箱查询,避免写函数导致索引失效
CREATE INDEX idx_users_lower_email ON users (lower(email));
-- 现在可以直接走索引
SELECT * FROM users WHERE lower(email) = 'someone@example.com';

-- 部分索引:只为活跃用户建索引,大大减少索引体积
CREATE INDEX idx_users_active ON users (email) WHERE active = true;

这两个特性的价值在于精准索引------不是所有数据都需要加速,只索引你最常查的那部分,存储和写入成本都降下来了。

6.3 执行计划分析

EXPLAIN ANALYZE查看SQL的实际执行计划:

sql 复制代码
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM products WHERE price < 100;

输出中重点关注Seq Scan (全表扫描,慢)还是Index Scan(索引扫描,快)。

如果想在图形界面操作,可以用pgAdmin执行可视化诊断。

七、JSONB与全文搜索

7.1 让关系型数据库也能"非结构化"

JSONB把JSON数据解析成二进制结构存储,支持索引,查询性能远超MySQL的JSON类型。

JSONB的核心操作符

sql 复制代码
-- 创建表
CREATE TABLE user_profiles (
    id SERIAL PRIMARY KEY,
    profile JSONB
);

INSERT INTO user_profiles (profile) VALUES 
('{"name": "张三", "age": 30, "address": {"city": "北京", "zip": "100000"}, "skills": ["Java", "Python"]}'),
('{"name": "李四", "age": 25, "address": {"city": "上海", "zip": "200000"}, "skills": ["Go", "Rust"]}');

-- 查询:-> 返回JSON对象,->> 返回文本
SELECT 
    profile -> 'name' AS name_json,
    profile ->> 'name' AS name_text,
    profile -> 'address' ->> 'city' AS city
FROM user_profiles;

-- 条件查询:包含操作符 @>
SELECT * FROM user_profiles 
WHERE profile @> '{"skills": ["Java"]}';

-- JSON路径查询:用 #>> 直接定位
SELECT profile #>> '{address,city}' FROM user_profiles;

7.2 全文搜索:让数据库变成搜索引擎

PostgreSQL内置了全文搜索引擎,使用tsvector(词位向量)和tsquery(查询表达式)两个核心类型:

sql 复制代码
-- 创建测试表
CREATE TABLE articles (
    id SERIAL PRIMARY KEY,
    title TEXT,
    content TEXT
);

INSERT INTO articles (title, content) VALUES 
('PostgreSQL 全文搜索入门', '全文搜索让PostgreSQL能像搜索引擎一样检索文本'),
('JSONB 实战指南', 'JSONB类型支持高效的半结构化数据存储和查询');

-- 基础全文搜索
SELECT title FROM articles
WHERE to_tsvector('english', title || ' ' || content) @@ to_tsquery('english', 'search');

-- 最佳实践:创建GIN索引加速全文搜索
ALTER TABLE articles ADD COLUMN search_vector tsvector
GENERATED ALWAYS AS (to_tsvector('english', title || ' ' || content)) STORED;

CREATE INDEX idx_articles_search ON articles USING GIN(search_vector);

-- 按相关度排序
SELECT title, ts_rank(search_vector, query) AS rank
FROM articles, to_tsquery('english', 'search') query
WHERE search_vector @@ query
ORDER BY rank DESC;

GENERATED ALWAYS AS ... STORED是PostgreSQL的一个巧妙设计------生成列自动维护,查询时直接用,不用每次都临时计算,性能和便捷性都兼顾了。

八、Java集成实战

作为Java后端,我们需要把数据库操作融入实际项目中。

这里以Spring Boot + MyBatis Plus为例。

8.1 添加依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- PostgreSQL 驱动 -->
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.7.0</version>
</dependency>
<!-- MyBatis Plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.7</version>
</dependency>

8.2 配置数据源

yaml 复制代码
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: postgres
    password: your_password
    driver-class-name: org.postgresql.Driver
  
  # 连接池配置(推荐HikariCP)
  datasource:
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      connection-timeout: 30000

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: auto

8.3 实体类和Mapper

java 复制代码
@Data
@TableName("products")
public class Product {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private BigDecimal price;
    private Integer stock;
    private String category;
    private List<String> tags;  // PostgreSQL原生支持数组
}

@Mapper
public interface ProductMapper extends BaseMapper<Product> {
    // 自定义查询:价格范围内的产品
    @Select("SELECT * FROM products WHERE price BETWEEN #{min} AND #{max}")
    List<Product> selectByPriceRange(@Param("min") BigDecimal min, 
                                      @Param("max") BigDecimal max);
}

8.4 Service层使用

java 复制代码
@Service
public class ProductService {
    @Autowired
    private ProductMapper productMapper;
    
    // 分页查询
    public IPage<Product> pageList(int pageNum, int pageSize) {
        Page<Product> page = new Page<>(pageNum, pageSize);
        return productMapper.selectPage(page, null);
    }
    
    // Lambda条件查询
    public List<Product> getInStockProducts() {
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
        wrapper.gt(Product::getStock, 0)
                .orderByDesc(Product::getPrice);
        return productMapper.selectList(wrapper);
    }
    
    // JSONB字段查询(使用原生SQL)
    @Select("SELECT * FROM products WHERE details @> #{jsonCondition}::jsonb")
    List<Product> selectByJsonCondition(@Param("jsonCondition") String jsonCondition);
}

九、PostgreSQL vs MySQL对比

9.1 核心差异一览表

对比维度 PostgreSQL MySQL
核心定位 企业级全功能数据库,主打标准兼容、复杂计算 互联网级OLTP数据库,主打高性能、简单易用
SQL标准兼容 对SQL:2023标准兼容度超90% 兼容度约70%,高级功能大量阉割
架构模型 单存储引擎+插件化扩展 多存储引擎,主推InnoDB
MVCC实现 快照隔离,读写永不阻塞 依赖undo log,存在锁竞争
可序列化隔离 严格SSI实现,高性能 本质是全表加锁,性能极差
扩展能力 插件生态极强,支持时序/向量/地理空间等 扩展能力有限,生态集中在分库分表
JSON支持 JSONB二进制存储,GIN索引,速度快300倍 JSON类型,查询性能较弱
高级SQL 窗口函数、CTE、全文搜索原生支持 MySQL 8.0后部分支持
开源协议 PostgreSQL License(宽松类BSD) GPLv2,修改源码需开源
适用场景 复杂查询、数据分析、金融、地理信息 高并发Web应用、内容管理、快速原型

PostgreSQL最大的优势在于功能完整性和标准合规性

PostgreSQL 对 SQL 标准的支持最为完整,这对复杂应用和数据分析至关重要。

国内越来越多的大厂开始从MySQL向PostgreSQL迁移,看中的正是它的SQL标准兼容性和插件扩展能力。

十、优缺点与适用场景

10.1 优点

  1. 功能丰富,一库通吃:支持JSON、数组、地理空间、时序数据等多种数据类型
  2. SQL标准兼容度高:迁移成本低,生态工具丰富
  3. 数据完整性保障强:原生支持完整外键约束、CHECK约束、排除约束
  4. 强大的并发性能:MVCC机制让读写互不阻塞,高并发写入领先于MySQL
  5. 扩展性极强:通过插件扩展可实现几乎所有企业级需求
  6. 插件生态成熟:PostGIS(地理信息)、pgvector(向量检索)、TimescaleDB(时序数据)等

10.2 缺点

  1. 学习曲线陡峭:功能多,每个特性的学习成本也相应增加
  2. 默认配置保守:通常需要调优才能发挥最佳性能
  3. 社区热点分散:插件多,"最佳实践"不集中
  4. 简单查询吞吐量:比MySQL略低(MySQL约20,000 tpmC,PostgreSQL约18,000 tpmC)
  5. VACUUM维护成本:MVCC产生的死元组需要定期清理

10.3 适用场景

强烈推荐PostgreSQL的场景:

  • 金融交易、订单系统(需要完整ACID和严格约束)
  • 复杂报表、数据分析系统(需要高级SQL和窗口函数)
  • JSON/半结构化数据存储(利用JSONB+GIN索引)
  • 地理信息系统(PostGIS是行业标准)
  • 全文搜索引擎(内置全文检索,无须Elasticsearch)
  • AI+向量检索应用(借助pgvector扩展)
  • 时序数据监控(借助TimescaleDB)

MySQL更适合的场景:

  • 高并发纯OLTP、简单CRUD的应用
  • 前期快速原型开发(配置简单、生态成熟)
  • 已有成熟的MySQL运维体系和工具链
  • 团队成员对PostgreSQL不熟悉的学习成本问题

总结

MySQL是"菜刀"式的数据库,锋利简单,一招吃遍天。

PostgreSQL是"瑞士军刀"式的数据库。它功能全面但学习门槛高。

没有哪个一定更好,但你需要了解这两把利器的各自神威。

我建议每个Java后端工程师,花两个月时间:

  • 读一遍PostgreSQL官方文档的"SQL Language"和"Server Administration"部分
  • 练一遍CRUD、索引、事务、JSONB、全文搜索所有本章例子的实际操作
  • 想一遍如果在你的业务里用PostgreSQL,架构哪里可以做得更好

当你熟悉了PostgreSQL的这些高级特性,你会发现------原来复杂需求真的可以用数据库一行SQL解决,而不是在业务代码里凑一千行的Java if-else。

这是数据库思维上的根本改变。

我希望这篇文章不仅帮你入了PostgreSQL的门,更帮你打开了多模态数据管理和复杂业务建模的一扇窗。

更多项目实战在我的技术网站:susan.net.cn/project

相关推荐
杨运交1 小时前
[025][Web模块]基于 Spring Boot 的请求日志过滤器设计与实现
前端·spring boot·后端
IT_陈寒1 小时前
React的useEffect里设状态?我又踩雷了
前端·人工智能·后端
云浪1 小时前
搞懂 Go WaitGroup:一篇文章彻底理解并发等待机制
后端·go
一 乐1 小时前
在线考试|基于Springboot的在线考试管理系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·毕设·在线考试管理系统
右耳朵猫AI1 小时前
Golang技术周刊 2026年第20周
开发语言·后端·golang
我是一颗柠檬2 小时前
【Redis】有序集合与位图Day5(2026年)
数据库·redis·后端·缓存
喵了几个咪2 小时前
Headless 后端实践:基于Go的企业级多栈管理系统脚手架
开发语言·vue.js·后端·golang·reactjs·gowind
小小龙学IT2 小时前
Go 并发模式深度解析:Fan-out/Fan-in 高效处理大规模数据流
开发语言·后端·golang
我是一颗柠檬2 小时前
【Redis】持久化机制Day6(2026年)
数据库·redis·后端·缓存·database