欢迎光临
我们一直在努力

PostgreSQL那些真正有辨识度的特性与优势

DB-Engines 六月份的一篇文章显示,PostgreSQL(以下简称 PG)的热度仍在持续上升,上半年的涨分幅度位列第一。

而在最新的数据库排行中,PG 也已经位列第四。

PG 这些年的热度增长,与开源、社区生态以及数据库市场本身的变化都有关系。

不过真正用过一段时间之后,会发现 PG 本身也确实有很多很有辨识度的设计。

除了普通的表、事务、索引和 JOIN,它还原生支持 JSONB、数组、Range、全文检索以及多种索引类型,再配合 PostGIS、pgvector、zhparser 等扩展,可以处理的数据类型比很多传统关系型数据库更加丰富。

我个人认为,PG 最有价值的一点在于:当业务需要一种新能力时,往往可以直接通过扩展在现有数据库体系内实现,而不必再额外引入一套新系统。

这篇文章就挑几个我觉得比较有代表性的地方聊一聊。


一、JSONB:关系型数据库里直接处理半结构化数据

PG 对 JSON 的支持已经深入到了数据库类型和查询体系中。

其中最常用的就是 jsonb:

CREATE TABLE devices (
id bigint PRIMARY KEY,
name text,
properties jsonb
);

例如不同设备可以拥有不同属性:

{
"model": "A100",
"temperature": true,
"voltage": 220
}

查询时可以直接访问 JSON 内部字段:

SELECT *
FROM devices
WHERE properties>>'model' = 'A100';

也可以判断 JSON 是否包含某段结构:

SELECT *
FROM devices
WHERE properties @> '{"temperature": true}';

JSONB 还可以配合 GIN 索引,对内部字段和包含关系进行加速。

这种设计在实际项目中很方便。

稳定、经常参与查询和关联的字段正常建列;设备参数、扩展配置、动态属性这一类结构变化较多的数据,则可以放进 JSONB。

这样既能保留关系型结构,又不需要为了几个不稳定字段频繁修改表结构。


二、数组本身就是一种字段类型

PG 可以直接把数组作为字段类型。

例如:

CREATE TABLE articles (
id bigint PRIMARY KEY,
title text,
tags text[]
);

一篇文章可以直接保存:

{"PostgreSQL","Database","Backend"}

查询是否包含某个标签:

SELECT *
FROM articles
WHERE tags @> ARRAY['PostgreSQL'];

这种写法也很有 PG 的风格。

像标签、权限集合、简单分类、少量状态集合,有时候关系并没有复杂到值得额外建立一张关联表。

这种情况下,数组可以让表结构更加直接。

当然,如果数组中的元素本身需要独立管理,或者涉及复杂关联、统计和约束,正常拆表通常还是更加合适。


三、Range:直接把“范围”当成数据

PG 原生提供 Range 类型,例如:

daterange
tsrange
tstzrange
int4range
int8range

于是预约时间可以直接定义成:

CREATE TABLE reservations (
id bigint,
period tstzrange
);

查询某段时间是否与已有预约重叠:

SELECT *
FROM reservations
WHERE period &&
'[2026-09-09 10:00, 2026-09-09 12:00)'::tstzrange;

这里的 && 表示两个范围存在重叠。

常见的设计通常会使用:

start_time
end_time

然后在查询中组合大于、小于等条件。

Range 则把“区间”本身变成了一种数据类型,同时提供包含、重叠、相邻等专门的运算。

在预约系统、任务执行窗口、会员有效期、价格区间等场景里,这种表达方式会自然很多。


四、Exclusion Constraint:把“不能冲突”写成数据库约束

数据库中最常见的唯一性约束是:

UNIQUE

它很适合解决“两个值不能相同”的问题。

但实际业务里还有很多规则并不是简单的相等关系。

例如:

同一个会议室的预约时间不能重叠。

PG 可以通过 EXCLUDE 直接表达:

EXCLUDE USING gist (
room_id WITH =,
period WITH &&
);

它表示:

同一个 room_id 下,两个 period 不能发生重叠。

这样一来,“预约时间不能冲突”就成为了数据库自身维护的规则。

即使以后存在多个服务、脚本或者后台任务同时写入数据,这条约束仍然有效。

相比只依赖应用层先查询、再判断,这种方式对并发场景也更加可靠。


五、全文检索和预分词

PG 自带 Full Text Search,并提供:

tsvector
tsquery

这样的专门类型。

例如:

SELECT to_tsvector(
'english',
'PostgreSQL provides powerful full text search'
);

数据库会把文本转换成适合搜索的词元表示。

实际项目中通常还会把处理后的 tsvector 保存下来,并建立 GIN 索引。

这样查询时可以直接使用已经生成好的搜索向量,避免每次搜索都重新处理整篇文本。

相比:

LIKE '%keyword%'

全文检索可以进一步处理词元、搜索条件组合以及相关度排序。

对于博客、文档、知识库以及包含大量文本字段的系统,这已经是一套相当完整的基础搜索能力。


六、zhparser:把中文分词接入 PostgreSQL

PG 自带的全文检索对英文比较自然,因为英文单词之间本身就有明显的空格边界。

中文处理起来会更复杂一些。

例如:

实验室数据质量管理平台

搜索系统首先要确定如何拆分成:

实验室
数据
质量
管理
平台

zhparser 就是 PG 生态中比较常见的中文分词扩展。

它可以把中文分词能力接入 PG 原本的全文检索体系,因此后续仍然能够继续使用:

tsvector
tsquery
GIN

这一整套机制。

对于内部管理系统、知识库、文档平台这类搜索规模没有特别夸张的项目,PG 配合 zhparser 已经可以承担不少中文搜索需求。

这样也能少维护一套额外的搜索基础设施。


七、PostGIS:地理位置不再只是两个浮点数

最简单的经纬度保存方式一般是:

latitude
longitude

但只要开始真正做地理查询,事情很快就会复杂起来。

例如:

  • 距离某个位置 5 公里以内有哪些设备;
  • 一个点是否位于某个区域;
  • 两个区域是否相交;
  • 一条路线经过了哪些区域。

PostGIS 是 PG 最具代表性的扩展之一。

它加入了:

geometry
geography

等空间数据类型。

例如:

SELECT *
FROM devices
WHERE ST_DWithin(
location,
:target_location,
5000
);

数据库可以直接完成空间距离计算。

除此之外,PostGIS 还能够处理不同坐标系之间的转换,以及点、线、面之间的大量空间关系。

对于地图、物流、设备管理、物联网(IoT)、车辆轨迹和区域分析等系统,这种能力非常实用。


八、pgvector:PostgreSQL 也可以直接做向量搜索

Embedding 普及之后,很多系统开始需要保存向量数据。

例如一段文本经过模型处理后,可能得到:

[0.13, -0.27, 0.81, …]

pgvector 为 PG 增加了真正的 vector 类型。

例如:

CREATE TABLE documents (
id bigint PRIMARY KEY,
content text,
embedding vector(1536)
);

之后就可以直接按照向量距离寻找相似内容:

SELECT *
FROM documents
ORDER BY embedding <=> :query_vector
LIMIT 10;

pgvector 还支持 HNSW、IVFFlat 等向量索引。

我觉得它比较有吸引力的一点,是向量数据可以继续和普通业务数据放在同一套查询体系中。

例如:

SELECT *
FROM documents
WHERE project_id = 100
ORDER BY embedding <=> :query_vector
LIMIT 10;

先按照 project_id 过滤业务范围,再进行向量相似度排序。

对于检索增强生成(RAG)、内部知识库和中等规模的语义搜索系统,这种组合方式可以减少不少额外架构。

如果业务量继续扩大、搜索需求进一步复杂,再考虑专门的向量数据库也完全来得及。


九、GIN、GiST、BRIN:PostgreSQL 的索引不只有 B-Tree

PG 的索引体系也很有特点。

除了最常见的 B-Tree,还经常可以看到:

  • GIN:常用于 JSONB、数组、全文检索等“一条数据包含多个元素”的场景;
  • GiST:常见于 Range、空间数据以及更复杂的关系查询;
  • BRIN:适合大型、数据值与物理存储顺序高度相关的表,例如持续追加的日志和时序数据。

例如一张长期按照时间顺序追加的亿级日志表,如果每条记录的时间和物理存储位置本身就高度相关,那么 BRIN 会很有意思。

它不需要像普通 B-Tree 一样记录大量精细索引项,而是记录一段数据块的大致取值范围。

查询某个时间范围时,就可以快速排除大量完全无关的数据块。

所以 PG 索引体系真正有意思的地方,在于不同的数据特征可以使用完全不同的索引策略。


十、扩展机制才是这些能力背后的基础

前面提到的:

zhparser
PostGIS
pgvector

都属于 PG 扩展生态的一部分。

PG 的扩展机制很深入。

扩展可以加入:

新的数据类型
新的函数
新的运算符
新的索引能力
新的查询行为

例如 PostGIS 安装之后,空间数据就可以直接参与:

SELECT
WHERE
JOIN
INDEX
ORDER BY

这些常规数据库操作。

pgvector 也是类似。

向量会成为 PG 可以识别、计算和建立索引的数据类型。

因此 PG 的扩展生态能够不断出现新的能力,同时又保持在原有 SQL、事务、权限和索引体系之内。

我觉得这其实是 PG 很有辨识度的一点。


PostgreSQL 的优势到底体现在哪里

如果业务只有几张表,再加上一些简单CRUD,那么 PG 的很多能力确实很难体现出来。

随着系统的数据类型逐渐复杂,它的特点才会越来越明显。

例如一个系统可能同时存在:

关系数据
动态 JSON
标签数组
中文文档
地理位置
Embedding

使用 PG 时,可以根据数据自身的特点选择对应能力。

普通业务关系继续使用表、外键、事务和 JOIN;

动态属性使用 JSONB;

标签集合可以考虑数组;

时间窗口可以使用 Range;

全文搜索使用 tsvector;

中文分词接入 zhparser;

空间数据交给 PostGIS;

语义搜索则可以使用 pgvector。

这些能力又可以继续共享 PG 原有的事务、权限、备份和 SQL 查询体系。

这也是我觉得 PG 很有价值的地方:

随着业务复杂度提高,它依然可以继续容纳更多不同形式的数据,很多需求不用一开始就拆成好几套独立基础设施。

当然,这并不意味着 PG 可以取代所有专业系统。

数据规模、访问模式和业务需求到了某个阶段,ES、专业时序数据库、向量数据库或者其他系统依然有自己的优势。

PG 更吸引人的地方,在于很多项目可以先从一套相对统一的数据库体系开始,等真正出现明确瓶颈之后再拆分。

赞(0)
未经允许不得转载:171主机测评 » PostgreSQL那些真正有辨识度的特性与优势
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址