能当关系型数据库还能玩对象特性,能拆复杂查询还能自动管库存,PostgreSQL 凭什么这么香?
url: /posts/b5474d1480509c5072085abc80b3dd9f/
title: 能当关系型数据库还能玩对象特性,能拆复杂查询还能自动管库存,PostgreSQL凭什么这么香?
date: 2025-09-20T06:58:38+08:00
lastmod: 2025-09-20T06:58:38+08:00
author: cmdragon
summary:
PostgreSQL是一种对象-关系型数据库(ORDBMS),结合了关系型数据库的结构化特性和对象型数据库的灵活性,支持自定义数据类型和方法。它起源于1986年的POSTGRES项目,1996年开源后成为全球流行的数据库之一。PostgreSQL的核心特性包括复杂查询、事务完整性、MVCC(多版本并发控制)、外键和触发器,能够高效处理高并发和复杂数据操作。此外,PostgreSQL具有强大的可扩展性,支持自定义数据类型、函数和索引,满足多样化需求。
categories:
- postgresql
tags:
- 基础入门
- 对象-关系型数据库
- 数据库特性
- 事务完整性
- MVCC
- 自定义数据类型
- 触发器


扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长
发现1000+提升效率与开发的AI工具和实用程序:https://tools.cmdragon.cn/
1.1 PostgreSQL的核心定位:对象-关系型数据库(ORDBMS)
如果你接触过数据库,一定听过“关系型数据库”(比如MySQL、Oracle)——它们用表、行、列存储数据,用SQL语言操作。而PostgreSQL不一样,它是对象-关系型数据库(ORDBMS):既保留了关系型数据库的“规矩”(比如表结构、SQL标准),又融入了对象型数据库的“灵活”(比如自定义数据类型、方法)。
举个通俗的例子:如果要存储“几何图形”数据,传统关系型数据库可能会用多个字段(比如x1,y1,x2,y2
存矩形),但PostgreSQL允许你自定义一个rectangle
类型,直接存储矩形的坐标,还能给这个类型加个area()
方法(计算面积)。这就是“对象”特性的体现——把“数据”和“操作数据的方法”打包在一起;而“关系”特性则是它依然遵守SQL规则,能用表、JOIN、外键这些传统玩法。
1.2 PostgreSQL的起源与发展:从伯克利到全球社区
PostgreSQL不是“凭空造出来的”,它的祖先叫POSTGRES,是1986年美国加州大学伯克利分校(UC Berkeley)的科研项目。当时的关系型数据库有个大痛点:无法处理复杂数据类型(比如几何图形、文档)。POSTGRES的目标就是解决这个问题——它首次提出“对象-关系”模型,允许用户自定义数据类型和函数。
1996年,POSTGRES的开源版本发布,改名为“PostgreSQL”(意为“PostgreSQL是POSTGRES的后继者”)。从那以后,全球开发者一起维护它,现在已经更新到17版本(2024年),成为最流行的开源数据库之一。
1.3 PostgreSQL的核心特性:为什么它能打?
PostgreSQL能火,不是因为“开源免费”,而是因为它的“硬实力”——支持很多现代数据库的核心特性,而且做得很极致。我们逐一拆解:
1.3.1 复杂查询:搞定“绕弯子”的需求
PostgreSQL的查询能力堪称“全能”,支持:
- 多表JOIN:比如查“每个订单的用户姓名和商品名称”,可以把
orders
(订单表)、users
(用户表)、products
(商品表)JOIN起来; - 子查询:比如查“工资高于平均工资的员工”,先用子查询算出平均工资,再筛选;
- CTE(Common Table Expressions):用
WITH
语句把复杂查询拆成“临时表”,比如查“每个部门的TOP3工资员工”,用CTE先算每个部门的工资排名,再取前3。
举个电商系统的实际例子——热销商品统计:
-- 第一步:用CTE算出每个商品的总销量
WITH product_sales AS (SELECT product_id, SUM(quantity) AS total_soldFROM ordersGROUP BY product_id
)
-- 第二步:关联商品表,得到热销TOP10
SELECT p.name, ps.total_sold
FROM products p
JOIN product_sales ps ON p.id = ps.product_id
ORDER BY ps.total_sold DESC LIMIT 10;
这个查询用CTE拆解了复杂逻辑,PostgreSQL处理起来毫无压力。
1.3.2 事务完整性:保证数据“不出错”
你肯定遇到过“转账失败”的坑:从A账户扣了钱,B账户却没收到——这就是“事务不完整”。PostgreSQL支持ACID特性,彻底解决这个问题:
- 原子性(Atomicity):事务里的操作要么全做,要么全不做。比如转账的两个步骤(扣钱、加钱),只要有一个失败,整个事务回滚;
- 一致性(Consistency):事务前后数据要符合规则。比如你的账户余额不能是负数,PostgreSQL会自动检查;
- 隔离性(Isolation):多个事务同时运行,互不干扰。比如你在查余额时,别人在转账,你看到的是转账前的余额;
- 持久性(Durability):事务提交后,数据永远不会丢(即使服务器宕机)。
1.3.3 MVCC:让“读写”互不干扰
传统数据库里,“读”和“写”会互相阻塞——比如你在看数据时,别人不能改;别人在改数据时,你不能看。这在高并发场景下(比如秒杀、电商大促)会卡死。
PostgreSQL用**MVCC(多版本并发控制)**解决了这个问题:每个事务看到的数据是一个“快照”。比如:
- 用户A在“读”订单表(看自己的订单);
- 用户B在“写”订单表(修改订单状态);
- 用户A看到的还是修改前的订单状态,直到用户B提交事务。
这样一来,“读”和“写”可以同时进行,不会阻塞,大大提高了并发性能。
1.3.4 外键、触发器:自动维护数据“规矩”
PostgreSQL还能帮你“自动做事”,不用手动检查数据:
- 外键(Foreign Key):比如
orders
表的user_id
必须指向users
表的id
。如果有人想插入一个不存在的user_id
,PostgreSQL会直接拒绝,防止“无效订单”; - 触发器(Trigger):比如当订单状态改为“完成”时,自动减少商品库存。你不用写代码调库存接口,PostgreSQL会帮你做:
-- 1. 创建触发器函数(要做的事情)
CREATE OR REPLACE FUNCTION update_inventory()
RETURNS TRIGGER AS $$
BEGIN-- 减少商品库存(NEW代表新插入的订单记录)UPDATE productsSET stock