PostgreSQL可以替代MongoDB吗?

最近,一篇《从 MongoDB 到 PostgreSQL 的大迁移》引发了 MongoDB 用户的关注,在我们的用户群组里有朋友 @flyingcrp 问了这样一个问题 —— 为什么PG上的一个插件或者功能点就能顶的上别人一个完整的产品?当然也有持相反观点的朋友 —— PG的 JSON 性能肯定比不过细分领域的专业产品,这个讨论引起了我的兴趣,这些命题成立吗?

通常来说,讨论性能问题离不开具体的场景。我上一次和 MongoDB 打交道是在 2016 年 —— 我使用 Multicorn FDW 迁移了一套服务于生产在线业务的 MongoDB 到 PostgreSQL。把1TB出头规模的数据,搬到使用同样硬件的 PostgreSQL 上。在迁移的过程中,我对 MongoDB 留下了极差的印象 —— 我花费了很多时间清洗模式错乱的垃圾数据;在性能方面我已经忘掉了具体的数字,但还记得迁移至 PostgreSQL 后,性能有了突飞猛进的改善。之后的这么多年里,我没有再和 MongoDB 打过交道,确实也不知道 MongoDB 后面有没有什么长进。

于是,我做了一些简单的检索与研究,结果发现了一些非常有趣且震惊的结论:

  • 在关于 JSON 存储检索性能上,PG 吊打 MongoDB!
  • MongoDB 在正确性上比 MySQL 还要垃圾得多!
  • MongoDB 已经开始过气,流行度趋势下跌

我在 Reddit 上看到一个帖子,怒斥 MongoDB 的问题,最令我震惊的莫过于 MongoDB 还有这么一段轶事 —— 在 3.2 的时候,拿着嵌入的 PostgreSQL 作为其“分析引擎”。而且做法和我 2016 年搞数据迁移的方式如出一辙 —— 都是用 Multicorn 编写的 FDW。


关于性能

Performance Benchmark: PostgreSQL vs. MongoDB @ 2020

Can PostgreSQL with its JSONB column type replace MongoDB? @ 2023-08


关于正确性

MongoDB and Jepsen

JEPSEN MongoDB 4.2.6


关于流行度

StackOverflow Developer Survey 2017 - 2023

DB-Engine Ranking - Trend Popularity


关于社区

JSON/JSONB, FerretDB, mongo_fdw

The Great Migration from MongoDB to PostgreSQL


关于黑历史

Doubt regarding PostgreSQL vs Mongodb

MongoDB 3.2: Now Powered by PostgreSQL


小结

Why You Should Never Use MongoDB

群友讨论的时候抛出了一个有趣的问题,研究了一下发现 MongoDB 实在是太垃圾了,无论是性能还是正确性都被PG吊打。正好最近喷云厂商太多了,应该回归一下数据库主业,清明节准备写一篇批判 MongoDB 的文章。

性能这种要看具体场景的场景。作为一个特定经验:我在 2016 年的时候用 MongoDB FDW 迁移了一套 MongoDB 到同硬件上的 PG,性能反正好了很多。但这么多年过去了,我也不知道现在 MongoDB 怎么样了。

首先,MongoDB 公司被发现在性能方面大量撒谎。

然后人们发现该产品的数据质量也很差。

然后人们发现“无模式”实际上意味着你拥有数百万个模式。

然后人们发现MongoDB的报告子系统实际上是一个嵌入式的Postgres数据库。

然后人们发现缺乏连接实际上是一个巨大的问题。而且在繁忙的 MongoDB 集群上回填旧数据可能需要数周时间。

最后人们发现,在存储 json 的一系列基准测试中,Postgres 比 MongoDB 更快。

因此,从这一点来看,MongoDB 就像 NoSQL 世界中的 MySQL:有太多谎言、太多夸张、太多坏建议。我们中的许多人都希望永远不再看到 mongodb。

学习如何有效使用文档数据库并不需要成为营销部门的鹦鹉。这意味着了解优势、劣势和设计模式:

数据质量:当 mongodb 复制不是原子的并且您可以覆盖部分记录时 - 您会怎么做?

无模式:实际上意味着“数百万个模式”——每行可能包含不同类型的不同字段。或者您很严格,坚持使用单一模式,并频繁进行模式迁移。这违背了公司的建议,违背了他们的“无模式”公关,并且在大型数据库上可能需要很长时间。

连接:是一种非常强大的适应性功能。最终,大多数人发现他们需要 mongodb 返回包含或被其他数据过滤的文档。例如,不仅要返回交易时的 customer_id,还要返回截至今天的customer_name ?很简单,只需连接到您的客户表即可。当连接速度非常慢时,您将失去大量的灵活性。

在某些时候和某些地方,mongodb 可能有意义。但就像 mysql 的领导层 20 年前告诉大家,90% 的开发人员不需要事务、视图、子选择、联合等一样,MongoDB 给人们带来了很多糟糕的建议。

PostgreSQL会修改开源许可证吗?

作者:Jonathan Katz,PostgreSQL 核心组成员(1 of 7),AWS RDS 首席产品经理

译者:冯若航,PostgreSQL 专家,Free RDS PG Alternative —— Pigsty 作者


PostgreSQL会修改开源许可证吗

声明:我是PostgreSQL 核心组 的成员,但本文内容是我的个人观点,并非 PostgreSQL 官方声明 …… 除非我提供了指向官方声明的链接

今天得知 Redis 项目将不再使用开源许可证发布,我感到非常遗憾。原因有二:一是作为长期的 Redis 用户和较早的采用者,二是作为一个开源贡献者。对于开源商业化这件事的挑战,我不得不说确实感同身受 —— 特别是我曾站在针锋相对的不同阵营之中(译注:作者也是 AWS RDS 首席产品经理)。我也清楚这些变化对下游的冲击,它们可能对用户采纳、应用技术的方式产生颠覆性的影响。

每当开源许可证领域出现重大变动时,尤其是在数据库及相关系统中(例如 MySQL => Sun => Oracle 就是第一个映入我脑海的),我总会听到这样的问题:“PostgreSQL会修改其许可证吗?”

PostgreSQL 的网站上其实 有答案

PostgreSQL会使用不同的许可证发布吗?PostgreSQL 全球开发组(PGDG)依然致力于永远将 PostgreSQL 作为自由和开源软件提供。我们没有更改 PostgreSQL 许可证,或使用不同许可证发布 PostgreSQL 的计划。

声明:上面这段确实是我参与撰写的

PostgreSQL许可证(又名 “协议” — Dave Page 和我在这个词上来回辩论挺有意思的)是一个开源倡议组织(OSI)认可的许可证,采用非常宽松的许可模型。至于它与哪个许可证最为相似,我建议阅读 Tom Lane在2009年写的这封电子邮件 (大意是:更接近 MIT 协议,叫 BSD 也行)。

尽管这么说,但 PostgreSQL不会改变许可证,还是有一些原因在里面的:

  • 许可证的名字就叫 “PostgreSQL许可证” —— 你都用项目来命名许可证了,还改什么协议?
  • PostgreSQL项目发起时,以开源社区协作为主旨,意在防止任何单一实体控制本项目。这一点作为项目的精神主旨已经延续了近三十年时间了,并且在项目 项目政策 中有着明确体现。
  • Dave Page 在这封邮件中明确表示过 😊

那么真正的问题就变成了,如果 PostgreSQL 要改变许可证,会出于什么理由呢?通常变更许可证的原因是出于商业决策 —— 但看起来围绕 PostgreSQL 的商业业务与 PostgreSQL 的功能集合一样强壮。冯若航(Vonng)最近写了一篇博客文章,突出展现了围绕 PostgreSQL 打造的软件与商业生态,这还仅仅是一部分。

我说 “仅仅是一部分” 的意思是,在历史上和现在还有更多的项目和商业,是围绕着 PostgreSQL 代码库的某些部分构建的。这些项目中许多都使用了不同的许可证发布,或者干脆就是闭源的。但它们也直接或间接地推动了PostgreSQL 的采用,并使 PostgreSQL 协议变得无处不在。

但 PostgreSQL 不会改变其许可证的最大原因是,这将对所有 PostgreSQL 用户产生不利影响。对一项技术来说,建立信任需要很长时间,尤其是当该技术经常用于应用程序最关键的部分:数据存储与检索。PostgreSQL赢得了良好的声誉 —— 凭借其久经考验的架构、可靠性、数据完整性、强大的功能集、可扩展性,以及背后充满奉献精神的开源社区,始终如一地提供优质、创新的解决方案。修改 PostgreSQL 的许可证将破坏该项目过去近三十年来建立起的所有良好声誉。

尽管 PostgreSQL 项目确实有不完美之处(我当然也对这些不完美的地方有所贡献),但 PostgreSQL 许可证对PostgreSQL 社区和整个开源界来说,确实是一份真正的礼物,我们将继续珍惜并帮助保持 PostgreSQL 真正的自由和开源。毕竟,官网上也是这么说的 ;)

译者评论

能被 PostgreSQL 全球社区核心组成员提名推荐,我感到非常荣幸。上文中 Jonathan 提到我的文章是《PostgreSQL正在吞噬数据库世界》,英文版为《PostgreSQL is Eating The Database World》。发布于 Medium:https://medium.com/@fengruohang/postgres-is-eating-the-database-world-157c204dcfc4 ,并在 HackerNews ,X,LinkedIn 上引起相当热烈的讨论。

Redis 变更其许可证协议,是开源软件领域又一里程碑式的事件 —— 至此,所有头部的 NoSQL 数据库 ,包括 MongoDB, ElasticSearch,加上 Redis ,都已经切换到了 SSPL —— 一种不被 OSI 承认的许可证协议。

Redis 切换为更为严格的 SSPL 协议的核心原因,用 Redis Labs CEO 的话讲就是:“多年来,我们就像个傻子一样,他们拿着我们开发的东西大赚了一笔”。“他们”是谁? —— 公有云。切换 SSPL 的目的是,试图通过法律工具阻止这些云厂商白嫖吸血开源,成为体面的社区参与者,将软件的管理、监控、托管等方面的代码开源回馈社区。

不幸的是,你可以强迫一家公司提供他们的 GPL/SSPL 衍生软件项目的源码,但你不能强迫他们成为开源社区的好公民。公有云对于这样的协议往往也嗤之以鼻,大多数云厂商只是简单拒绝使用AGPL许可的软件:要么使用一个采用更宽松许可的替代实现版本,要么自己重新实现必要的功能,或者直接购买一个没有版权限制的商业许可。

当 Redis 宣布更改协议后,马上就有 AWS 员工跳出来 Fork Redis —— “Redis 不开源了,我们的分叉才是真开源!” 然后 AWS CTO 出来叫好,并假惺惺的说:这是我们员工的个人行为 —— 堪称是现实版杀人诛心。而同样的事情,已经发生过几次了,比如分叉 ElasticSearh 的 OpenSearch,分叉 MongoDB 的 DocumentDB。

因为引入了额外的限制与所谓的“歧视”条款,OSI 并没有将 SSPL 认定为开源协议。因此使用 SSPL 的举措被解读为 —— “Redis 不再开源”,而云厂商的各种 Fork 是“开源”的。从法律工具的角度来说,这是成立的。但从朴素道德情感出发,这样的说法对于 Redis 来说是极其不公正的抹黑与羞辱。

正如罗翔老师所说:法律工具的判断永远不能超越社区成员朴素的道德情感。如果协和与华西不是三甲,那么丢脸的不是这些医院,而是三甲这个标准。如果年度游戏不是巫师3,荒野之息,博德之门,那么丢脸的不是这些厂商,而是评级机构。如果 Redis 不再算“开源”,真正应该感到汗颜的应该是OSI 与开源这个理念。

越来越多的知名开源软件,都开始切换到敌视针对云厂商白嫖的许可证协议上来。不仅仅是 Redis 与 MongoDB,ElasticSearch 在 2021 年也从 Apache 2.0 修改为 SSL 与 ElasticSearch,知名的开源软件 MinIO 与 Grafana 分别在 2020,2021年从 Apache v2 协议切换到了 AGPLv3 协议。

一些老牌的开源项目例如 PostgreSQL ,正如 Jonathan 所说,历史沉淀(三十年的声誉!)让它们已经在事实上无法变更开源协议了。但我们可以看到,许多新强力的 PostgreSQL 扩展插件开始使用 AGPLv3 作为默认的开源协议,而不是以前默认使用的 BSD-like / PostgreSQL 友善协议。例如分布式扩展 Citus,列存扩展 Hydra,ES全文检索替代扩展 BM25,OLAP 加速组件 PG Analytics …… 等等等等。包括我们自己的 PostgreSQL 发行版 Pigsty,也在 2.0 的时候由 Apache 协议切换到了 AGPLv3 协议,背后的动机都是相似的 —— 针对软件自由的最大敌人 —— 云厂商进行反击。

在抵御云厂商白嫖的实践中,修改协议是最常见的做法:但AGPLv3 过于严格容易敌我皆伤,SSPL 因为明确表达这种敌我歧视,不被算作开源。业界需要一种新的歧视性软件许可证协议,来达到名正言顺区分敌我的效果。使用双协议进行明确的边界区分,也开始成为一种主流的开源商业化实践。

真正重要的事情一直都是软件自由,而“开源”只是实现软件自由的一种手段。而如果“开源”的理念无法适应新阶段矛盾斗争的需求,甚至会妨碍软件自由,它一样会过气,并不再重要,并最终被新的理念与实践所替代 —— 比如“本地优先”。

英文原文

WILL POSTGRESQL EVER CHANGE ITS LICENSE?

(Disclosure: I’m on the PostgreSQL Core Team, but what’s written in this post are my personal views and not official project statements…unless I link to something that’s an official project statement ;)

I was very sad to learn today that the Redis project will no longer be released under an open source license. Sad for two reasons: as a longtime Redis user and pretty early adopter, and as an open source contributor. I’ll preface that I’m empathetic to the challenges of building businesses around open source, having been on multiple sides of this equation. I’m also cognizant of the downstream effects of these changes that can completely flip how a user adopts and uses a piece of technology.

Whenever there’s a shakeup in open source licensing, particularly amongst databases and related systems (MySQL => Sun => Oracle being the one that first springs to mind), I’ll hear the question “Will PostgreSQL ever change its license?”

The PostgreSQL website has an answer:

Will PostgreSQL ever be released under a different license? The PostgreSQL Global Development Group remains committed to making PostgreSQL available as free and open > source software in perpetuity. There are no plans to change the PostgreSQL License or release PostgreSQL under a different license.

(Disclosure: I did help write the above paragraph).

The PostgreSQL Licence (aka “License” – Dave Page and I have fun going back and forth on this) is an Open Source Initiative (OSI) recognized license, and has a very permissive model. In terms of which license it’s most similar to, I defer to this email that Tom Lane wrote in 2009.

That said, there are a few reasons why PostgreSQL won’t change it’s license:

The question then becomes - is there a reason that PostgreSQL would change its license? Typically these changes happen as part of a business decision - but it seems that business around PostgreSQL is as robust as its feature set. Ruohang Feng (Vonng) recently wrote a blog post that highlighted just a slice of the PostgreSQL software and business ecosystem that’s been built around it, which is only possible through the PostgreSQL Licence. I say “just a slice” because there’s even more, both historically and current, projects and business that are built up around some portion of the PostgreSQL codebase. While many of these projects may be released under different licenses or be closed source, they have helped drive, both directly and indirectly, PostgreSQL adoption, and have helped make the PostgreSQL protocol ubiquitous.

But the biggest reason why PostgreSQL would not change its license is the disservice it would do to all PostgreSQL users. It takes a long time to build trust in a technology that is often used for the most critical part of an application: storage and retrieval of data. PostgreSQL has earned a strong reputation for its proven architecture, reliability, data integrity, robust feature set, extensibility, and the dedication of the open source community behind the software to consistently deliver performant and innovative solutions. Changing the license of PostgreSQL would shatter all of the goodwill the project has built up through the past (nearly) 30 years.

While there are definitely parts of the PostgreSQL project that are imperfect (and I certainly contribute to those imperfections), the PostgreSQL Licence is a true gift to the PostgreSQL community and open source in general that we’ll continue to cherish and help keep PostgreSQL truly free and open source. After all, it says so on the website ;)

PostgreSQL正在吞噬数据库世界

PostgreSQL 并不是一个简单的关系型数据库,而是一个数据管理的抽象框架,具有吞噬整个数据库世界的力量。而这也是正在发生的事情 —— “一切皆用 Postgres” 已经不再是少数精英团队的前沿探索,而是成为了一种进入主流视野的最佳实践。


OLAP 领域迎来踢馆者

在 2016 年的一次数据库沙龙里,我提出了一个观点: 现在 PostgreSQL 生态的一个主要遗憾是,缺少一个足够好的列式存储分析插件来做 OLAP 分析。尽管PostgreSQL 本身提供了很强大的分析功能集,应付常规的分析任务绰绰有余。但在较大数据量下全量分析的性能,相比专用的实时数仓仍然有些不够看。

以分析领域的权威评测 Clickbench 为例,我们在其中标注出了 PostgreSQL 与生态扩展插件以及兼容衍生数据库在其中的性能表现。原生未经过调优的 PostgreSQL 表现较为拉垮(x1050),但经过调优后可以达到(x47);此外还有三个与分析有关系的扩展:列存 Hydrax42),时序扩展 TimescaleDBx103),以及分布式扩展 Citusx262)。

pg-eat-clickbench.png

这样的分析性能表现不能说烂,因为比起 MySQL,MariaDB 这样的纯 OLTP 数据库的辣眼表现(x3065,x19700)确实好很多;但第三梯队的性能表现也绝对说不上足够好,与专注于 OLAP 的第一梯队组件:Umbra,ClickHouse,Databend,SelectDB(x3~x4)相比,在分析性能上仍然有十几倍的性能差距。食之无味,弃之可惜。

然而, ParadeDB DuckDB 的出现改变了这一点!

ParadeDB 提供的 PG 原生扩展 pg_analytics 实现了第二梯队(x10)的性能水准,与第一梯队只有 3~4 倍的性能差距。相对于其他功能上的收益,这种程度的性能差距通常是可以接受的 —— ACID,新鲜性与实时性,无需 ETL、额外学习成本、维护独立的新服务,更别提它还提供了 ElasticSearch 质量的全文检索能力。

DuckDB 则专注于 OLAP ,将分析性能这件事做到了极致(x3.2) —— 略过第一名 Umbra 这种学术研究型闭源数据库,DuckDB 也许是 OLAP 实战性能最快的数据库了。它并不是 PG 的扩展插件,但它是一个嵌入式文件数据库,而 DuckDB FDW 以及 pg_quack 这样的 PG 生态项目,能让 PostgreSQL 充分利用 DuckDB 带来的完整分析性能红利!

ParadeDB 与 DuckDB 的出现让 PostgreSQL 的分析性能来到了 OLAP 的第一梯队与金字塔尖,弥补了 PostgreSQL 在 OLAP 性能这最后一块关键短板。


分久必合的数据库领域

数据库诞生伊始,并没有 OLTP 与 OLAP 的分野。OLAP 数据仓库从数据库中“独立”出来,已经是上世纪九十年代时候的事了 —— 因为传统的 OLTP 数据库难以支撑起分析场景下的查询模式,数据量与性能要求。

在相当一段时间里,数据处理的最佳实践是使用 MySQL / PG 处理 OLTP 工作负载,并通过 ETL 将数据同步到专用的 OLAP 组件中去处理,比如 Greenplum, ClickHouse, Doris, Snowflake 等等。

与许多 “专用数据库” 一样,专业的 OLAP 组件的优势往往在于性能 —— 相比原生 PG 、MySQL 上有 1~3 个数量级的提升;而代价则是数据冗余、 大量不必要的数据搬运工作、分布式组件之间缺乏一致性、额外的专业技能带来的复杂度成本、学习成本、以及人力成本、 额外的软件许可费用、极其有限的查询语言能力、可编程性、可扩展性、有限的工具链、以及与OLTP 数据库相比更差的数据完整性和可用性 —— 但这是一个合理的利弊权衡

然而天下大势,分久必合,合久必分硬件遵循摩尔定律又发展了三十年,性能翻了几个数量级,成本下降了几个数量级。在 2024 年的当下,x86 单机可以达到几百核 (512 vCPU EPYC 9754x2),几个TB的内存,单卡 NVMe SSD 可达 64TB,全闪单机柜 2PB ;S3 这样对象存储更是能实现几乎没有上限的存储。

io-bandwidth.png

硬件的发展解决了数据量的问题,而数据库软件的发展(PostgreSQL,ParadeDB,DuckDB)解决了查询模式的问题,而这导致分析领域 —— 所谓的“大数据” 行业基本工作假设面临挑战。

正如 DuckDB 发表的宣言《大数据已死》所主张的:大数据时代已经结束了 —— 大多数人并没有那么多的数据,大多数数据也很少被查询。大数据的前沿随着软硬件发展不断后退,99% 的场景已经不再需要所谓“大数据”了。

如果 99% 的场景甚至都可以放在一台计算机上用单机/主从的 DuckDB 或 PostgreSQL 搞定,那么使用专用的分析组件还有多少意义?如果每台手机都可以自由自主收发短信,那么 BP 机还有什么存在价值?(北美医院还在用BP机,正好比也还有 1% 不到的场景也许真的需要“大数据”)

基本工作假设的变化,将重新推动数据库世界从百花齐放的“合久必分”阶段,走向“分久必合”的阶段,从大爆发到大灭绝,大浪淘沙中,新的大一统超融合数据库将会出现,重新统一 OLTP 与 OLAP。而承担重新整合数据库领域这一使命的会是谁?


吞食天地的 PostgreSQL

数据库领域有许多“细分领域”:时序数据库,地理空间数据库,文档数据库,搜索数据库,图数据库,向量数据库,消息队列,对象数据库。而 PostgreSQL 在任何一个领域都不会缺席。

一个 PostGIS 插件,成为了地理空间事实标准;一个 TimescaleDB 扩展,让一堆“通用”时序数据库尴尬的说不出话来;一个向量扩展 PGVector 插件,更是让整个**专用向量数据库细分领域** 变成笑话。

同样的事情已经发生过很多次,而现在,我们将在拆分最早,地盘最大的一个子领域 OLAP 分析中再次见证这一点。但 PostgreSQL 要替代的可不仅仅是 OLAP 数仓,它的野望是整个数据库世界!

pigsty-ecosystem.png

然 PostgreSQL 有何德何能,可当此大任?诚然 PostgreSQL 先进,但 Oracle 也先进;PostgreSQL 开源,但 MySQL 也开源。PostgreSQL 先进且开源,这是它与 Oracle / MySQL 竞争的底气,但要说其独一无二的特点,那还得是它的极致可扩展性,与繁荣的扩展生态

pg-survey.png

用户选择 PostgreSQL 的原因:开源,先进,扩展

PostgreSQL 并不是一个简单的关系型数据库,而是一个数据管理的抽象框架,具有囊括一切,吞噬整个数据库世界的力量。而它的核心竞争力(除了开源与先进)来自可扩展性,即基础设施的可复用性与扩展插件的可组合性


PostgreSQL 允许用户开发功能模块,复用数据库公共基础设施,以最低的成本交付功能。例如,仅有两千行代码的向量数据库扩展 pgvector 与百万行代码的 PostgreSQL 在复杂度上相比可以说微不足道,但正是这“微不足道”的扩展,实现了完整的向量数据类型与索引能力,干翻了几乎所有专用向量数据库。

为什么?因为 PGVECTOR 作者不需要操心数据库的通用额外复杂度:事务 ACID,故障恢复,备份PITR,高可用,访问控制,监控,部署,三方生态工具,客户端驱动这些需要成百上千万行代码才能解决好的问题,只需要关注自己所需问题的本质复杂度即可。

vector-survey.jpg

向量数据库哪家强?

再比如,ElasticSearch 基于 Lucene 搜索库开发,而 Rust 生态有一个改进版的下一代 Tantivy 全文搜索库作为 Lucene 的替代;而 ParadeDB 只需要将其封装对接到 PostgreSQL 的接口上,即可提供比肩 ElasticSearch 的搜索服务。更重要的是,它可以站在 PostgreSQL 巨人的肩膀上,借用 PG 生态的全部合力(例如,与 PG Vector 做混合检索),不讲武德地用数据库全能王的力量,去与一个专用数据库单品来对比。


可扩展性带来的另一点巨大优势是扩展的可组合性,让不同扩展相互合作,产生出 1+1 » 2 的协同效应。例如,TimescaleDB 可以与 PostGIS 组合使用,提供时空数据支持;再比如,提供全文检索能力的 BM25 扩展可以和提供语义模糊检索的 PGVector 扩展组合使用,提供混合检索能力。

再比如,分布式扩展 Citus 可以将单机主从数据库集群,原地升级改造为透明水平分片的分布式数据库集群。而这个能力是可以与其他功能正交组合的,因此,PostGIS 可以成为分布式地理数据库,PGVector 可以成为分布式向量数据库,ParadeDB 可以成为分布式全文搜索数据库,诸如此类。


更强大的地方在于,扩展插件是独立演进的,不需要繁琐的主干合并,联调协作。因此可以 Scale —— PG 的可扩展性允许无数个团队并行探索数据库前研发展方向,而扩展全部都是的可选的,不会影响主干核心能力的稳定性。那些非常强大成熟的特性,则有机会以稳定的形态进入主干中。

通过极致可扩展性的魔法,PostgreSQL 做到了**守正出奇,实现了主干极致稳定性与功能敏捷性的统一。**扎实的基本盘配上惊人的演进速度,让它成为了数据库世界中的一个异数,改变了数据库世界的游戏规则。


改变游戏规则的玩家

PostgreSQL 的出现,改变了数据库领域的游戏规则:任何试图开发“新数据库内核”的团队,都需要经过这道试炼与考验 —— 相比开源免费、功能齐备的 Postgres,价值点在哪里?

至少到硬件出现革命性突破前,实用的通用数据库新内核都不太可能诞生了,因为任何单一数据库都无法与所有扩展加持下的 PG 在整体实力上相抗衡 —— 包括 Oracle,因为 PG 还有开源免费的必杀技。

而某个细分领域的数据库产品,如果能在单点属性(通常是性能)上相比 PostgreSQL 实现超过一个数量级的优势,那也许还有一个专用数据库的生态位存在。但通常用不了多久,便会有 PostgreSQL 生态的开源替代扩展插件滚滚而来。因为选择开发 PG 扩展,而不是一个完整数据库的团队会在追赶复刻速度上有碾压性优势!

因此,如果按照这样的逻辑展开,PostgreSQL 生态的雪球只会越滚越大,随着优势的积累,不可避免地进入一家独大的状态。在几年的时间内,实现 Linux 内核在服务器操作系统领域的状态。而各种开发者调研报告,数据库流行趋势都在印证着这一点。

pg-is-no1-2.png

StackOverflow 2023 调研结果,PostgreSQL 三项全能王

pg-is-no1-1.png

StackOverflow过去7年的数据库指标走势

在引领潮流的 HackerNews StackOverflow 上,PostgreSQL 早已成为了最受欢迎的数据库。许多新的开源项目都默认使用 PostgreSQL 作为首要,甚至唯一的数据库 —— 例如,给各种数据库做模式管理的 Bytebase。《云时代数据库DevOps:硅谷调研》也提出,许多新一代互联网公司都开始积极拥抱并 All in PostgreSQL。

正如《技术极简主义:一切皆用 Postgres 》所言:简化技术栈、减少组件、加快开发速度、降低风险并提供更多功能特性的方法之一就是 “一切皆用 Postgres”。Postgres 能够取代许多后端技术,包括 MySQL,Kafka、RabbitMQ、ElasticSearch,Mongo和 Redis,至少到数百万用户时都毫无问题。一切皆用 Postgres ,已经不再是少数精英团队的前沿探索,而是成为了一种进入主流视野的最佳实践。


还有什么可以做的?

我们已经不难预见到数据库领域的终局。但我们又能做什么,又应该做什么呢?

PostgreSQL 对于绝大多数场景都已经是一个足够完美的数据库内核了,在这个前提下,数据库内核卡脖子纯属无稽之谈。这些Fork PostgreSQL 和 MySQL 并以内核魔改作为卖点的所谓“数据库”基本没啥出息。

这好比今天我们看 Linux 操作系统内核一样,尽管市面上有这么多的 Linux 操作系统发行版,但大家都选择使用同样的 Linux 内核,吃饱了撑着魔改内核属于没有困难创造困难也要上,会被业界当成山炮看待。

同理,数据库内核本身已经不再是主要矛盾,焦点将会集中到两个方向上 —— 数据库扩展与数据库服务!前者体现为数据库内部的可扩展性, 后者体现为数据库外部的可组合性。而竞争的形式,正如操作系统生态一样 —— 集中于数据库发行版上。对于数据库领域来说,只有那些以扩展和服务作为核心价值主张的发行版,才有最终成功的可能。

做内核的厂商不温不火,MariaDB 作为 MySQL 的亲爹 Fork 甚至都已经濒临退市,而白嫖内核自己做服务与扩展卖 RDS 的 AWS 可以赚的钵满盆翻。投资机构已经出手了许多 PG 生态的扩展插件与服务发行版:Citus,TimescaleDB,Hydra,PostgresML,ParadeDB,FerretDB,StackGres,Aiven,Neon,Supabase,Tembo,PostgresAI,以及我们正在做的 Pigsty 。


PostgreSQL 生态中的一个困境就是,许多扩展插件,生态工具都是独立演进,各自为战的,没有一个整合者能将他们凝聚起来形成合力。例如,提供分析的 Hydra 会打一个包一个 Docker 镜像, PostgresML 也会打自己的包和镜像,各家只发行加装了自己扩展的 Postgres 镜像。而这些朴素的镜像与包也距离 RDS 这样完整的数据库服务相距甚远。

即使是类似于 AWS RDS 这样的服务提供商与生态整合者,在诸多扩展面前也依然力有所不逮,只能提供其中的少数。更多的强力扩展出于各种原因(AGPLv3 协议,多租户租赁带来的安全挑战)而无法使用。从而难以发挥 PostgreSQL 生态扩展的协同增幅作用。

这里列出了一些重要扩展,对比基于最新的 PostgreSQL 16 主干版本进行,截止至 2024-02-28

扩展类目 Pigsty RDS / PGDG 官方仓库 阿里云 RDS AWS RDS PG
加装扩展 自由加装 不允许 不允许
地理空间 PostGIS 3.4.2 PostGIS 3.3.4 / Ganos 6.1 PostGIS 3.4.1
雷达点云 PG PointCloud 1.2.5 Ganos PointCloud 6.1
向量嵌入 PGVector 0.6.1 / Svector 0.5.6 pase 0.0.1 PGVector 0.6
机器学习 PostgresML 2.8.1
时序扩展 TimescaleDB 2.14.2
水平分布式 Citus 12.1
列存扩展 Hydra 1.1.1
全文检索 pg_bm25 0.5.6
图数据库 Apache AGE 1.5.0
GraphQL PG GraphQL 1.5.0
OLAP pg_analytics 0.5.6
消息队列 pgq 3.5.0
DuckDB duckdb_fdw 1.1
模糊分词 zhparser 1.1 / pg_bigm 1.2 zhparser 1.0 / pg_jieba pg_bigm 1.2
CDC抽取 wal2json 2.5.3 wal2json 2.5
膨胀治理 pg_repack 1.5.0 pg_repack 1.4.8 pg_repack 1.5.0

许多关键扩展在RDS中并不可用

扩展是 PostgreSQL 的灵魂,无法自由使用扩展的 Postgres 就像做菜不放盐。只能和 MySQL 放在同一个 RDS 的框子里同台,龙游浅水,虎落平阳。

而这正是我们想要解决的首要问题之一。


知行合一的实践:Pigsty

虽然接触 MySQL 和 MSSQL 要早得多,但我在 2015 年第一次上手 PostgreSQL 时,就相信它会是数据库领域的未来了。快十年过去,我也从 PG 的使用者,管理者,变为了贡献者,开发者。也不断见证着 PG 走向这一目标。

在与形形色色的用户沟通交流中,我早已发现数据库领域的木桶短板不是内核 —— 现有的 PostgreSQL 已经足够好了,而是用好数据库内核本身的能力,这也是 RDS 这样的服务赚的钵满盆翻的原因。

但我希望这样的能力,应该像自由软件运动所倡导的理念那样,像 PostgreSQL 内核本身一样 —— 普及到每一个用户手中,而不是必须向赛博空间上的封建云领主花大价钱租赁。

所以我打造了 Pigsty —— 一个开箱即用的开源 PostgreSQL 数据库发行版,旨在凝聚 PostgreSQL 生态扩展的合力,并把提供优质数据库服务的能力普及到每个用户手中。

Pigsty 是 PostgreSQL in Great STYle 的缩写,意为 PostgreSQL 的全盛状态

我们提出了六点核心价值主张,对应 PostgreSQL 数据库服务中的的六个核心问题:Postgres 的可扩展性基础设施的可靠性图形化的可观测性服务的可用性工具的可维护性,以及扩展模块和三方组件可组合性

Pigsty 六点价值主张的首字母合起来,则为 Pigsty 提供了另外一种缩写解释:

Postgres, Infras, Graphics, Service, Toolbox, Yours.

属于你的图形化 Postgres 基础设施服务工具箱。

可扩展的 PostgreSQL 是这个发行版中最重要的价值主张。在刚刚发布的 Pigsty v2.6 中,我们整合了上面提到的 DuckdbFDW 与 ParadeDB 扩展,这两个插件让 PostgreSQL 的分析能力得到史诗级增强,而我们确保每个用户都能轻松用得上这样的能力。

pg-eat-regards.png

来自 ParadeDB 创始人与 DuckdbFDW 作者的感谢致意

我们希望整合 PostgreSQL 生态里的各种力量,并将其凝聚在一起形成合力,打造一个数据库世界中的 Ubuntu 发行版。而我相信,内核之争早已尘埃落定,而这里才会是数据库世界的未来竞争焦点。

  • PostGIS:提供地理空间数据类型与索引支持,GIS 事实标准 (& pgPointCloud 点云,pgRouting 寻路)
  • TimescaleDB:添加时间序列/持续聚合/分布式/列存储/自动压缩的能力
  • PGVector:添加 AI 向量/嵌入数据类型支持,以及 ivfflat 与 hnsw 向量索引。(& pg_sparse 稀疏向量支持)
  • Citus:将经典的主从PG集群原地改造为水平分片的分布式数据库集群。
  • Hydra:添加列式存储与分析能力,提供比肩 ClickHouse 的强力分析能力。
  • ParadeDB:添加 ElasticSearch 水准的全文搜索能力与混合检索的能力。(& zhparser 中文分词)
  • Apache AGE:图数据库扩展,为 PostgreSQL 添加类 Neo4J 的 OpenCypher 查询支持,
  • PG GraphQL:为 PostgreSQL 添加原生内建的 GraphQL 查询语言支持。
  • DuckDB FDW:允许您通过 PostgreSQL 直接读写强力的嵌入式分析数据库 DuckDB 文件 (& DuckDB CLI 本体)。
  • Supabase:基于 PostgreSQL 的开源的 Firebase 替代,提供完整的应用开发存储解决方案。
  • FerretDB:基于 PostgreSQL 的开源 MongoDB 替代,兼容 MongoDB API / 驱动协议。
  • PostgresML:使用SQL完成经典机器学习算法,调用、部署、训练 AI 模型。

Pigsty 支持的 180+ 扩展列表

开发者朋友们,你们的选择会塑造数据库世界的未来。希望我的这些工作,可以帮助你们更好的用好这世界上最先进的开源数据库内核 —— PostgreSQL。


参考阅读

Pigsty v2.6:PostgreSQL 踢馆 OLAP

技术极简主义:一切皆用Postgres

PG生态新玩家ParadeDB

DBA会被云淘汰吗?

令人惊叹的PostgreSQL可伸缩性

中国对PostgreSQL的贡献约等于零吗?

展望PostgreSQL的2024 (Jonathan Katz)

2023年度数据库:PostgreSQL (DB-Engine)

MySQL的正确性为何如此拉垮?

向量数据库凉了吗?

重新拿回计算机硬件的红利

数据库真被卡脖子了吗?

PG查询优化:观宏之道

FerretDB:假扮成MongoDB的PostgreSQL

如何用 pg_filedump 抢救数据?

PGSQL x Pigsty: 数据库全能王来了

Pigsty 特性与快速上手

PG先写脏页还是先写WAL?

PostgreSQL:世界上最成功的数据库

ISD数据集:分析全球120年气候变化

AI大模型与向量数据库 PGVECTOR

更好的开源RDS替代:Pigsty

PostgreSQL 到底有多强?

为什么PostgreSQL是最成功的数据库?

PG与Pigsty用户需求问卷调研结果

高可用PgSQL集群架构设计与落地

为什么说PostgreSQL前途无量?

Postgres本地化排序规则

PG复制标识详解(Replica Identity)

利用监控系统诊断PG慢查询

数据库集群管理概念与实体命名规范

PostgreSQL的KPI

PostgreSQL监控系统Pigsty概述

故障档案:PG安装扩展导致无法连接

PostgreSQL中的表锁

把PG放入Docker是一个好主意吗?

PostgreSQL监控系统概览

pg_dump导致的血案

PostgreSQL数据页面损坏修复

PostgreSQL关系膨胀:原理,监控与处理

探探PostgreSQL开发规约

并发异常那些事

PG好处都有啥?

IP归属地查询的高效实现

PostGIS高效解决行政区划归属查询问题

技术极简主义:一切皆用Postgres

微信公众号原文链接

本文由 Stephan Schmidt @ KingOfCoders 发表于 Hacker News 并引发热议[1]:使用 Postgres 替代 Kafka、RabbitMQ、ElasticSearch、Mongo 和 Redis 是一种切实可行的方式,这样做可以极大降低系统复杂度,并将敏捷性发挥到极致。


如何简化复杂度并快速前进:用 PostgreSQL 完成所有任务

欢迎,HN(Hacker News)读者们。技术是关于取舍的艺术。全面使用 PostgreSQL 完成所有工作,也是一种策略与权衡。显然,我们应根据需求选用合适的工具。很多情况下,这个工具就是 Postgres

在辅助许多初创企业的过程中,我观察到很多人过度复杂化他们的系统,这样做的公司远超过那些选择了过于简单工具的公司。如果你们拥有超过一百万用户,超过五十名开发者,并且你们确实需要 Kafka、Spark 和 Kubernetes,那么请便。如果你的系统数量比开发者还多,只用 Postgres 就是一个明智之选。

附言:全面使用 Postgres 并不意味着单台器搞定一切 ;-)


简单来说,一切皆可用 Postgres 解决

请神容易送神难,让复杂度溜进家里,再送走就没那么容易了。


然而,我们有极致简化的方案


在初创公司中简化技术栈、减少组件、加快开发速度、降低风险并提供更多功能特性的方法之一就是**“一切皆用 Postgres”**。Postgres 能够取代许多后端技术,包括 Kafka、RabbitMQ、ElasticSearch,Mongo和 Redis ,至少到数百万用户时都毫无问题。

使用 Postgres 替代 Redis 作为缓存,使用 UNLOGGED Table[3] 并用 TEXT 类型存储 JSON 数据,并使用存储过程来添加并强制执行过期时间,正如 Redis 所做的那样。

使用 Postgres 作为消息队列,采用 SKIP LOCKED[4] 来代替Kafka(如果你只需要消息队列的能力)。

使用加装了 TimescaleDB[5] 扩展的 Postgres 作为数据仓库。

使用 PostgreSQL 的 JSONB[6] 类型来存储、索引、搜索 JSON 文档,从而替代 MongoDB。

使用加装 pg_cron[7] 扩展的 Postgres 作为定时任务守护程序,在特定时间执行特定任务,例如发送邮件,或向消息队列中添加事件。

使用 Postgres + PostGIS 执行 地理空间查询[8]。

使用 Postgres 进行全文搜索[9],加装 ParadeDB 替代 ElasticSearch。

使用 Postgres 在数据库中生成JSON[10],免去服务器端代码编写,直接供 API 使用。

使用 GraphQL适配器[11],也可以让 PostgreSQL 提供 GraphQL 服务。

我已明言,一切皆可Postgres


关于作者 Stephan

作为一名CTO、临时CTO、CTO教练以及开发者,斯蒂芬在许多快速成长的初创公司的技术部门中都留下了自己的足迹。他在1981年左右,因为想编写视频游戏,就在一家百货公司自学了编程。斯蒂芬在乌尔姆大学(University of Ulm)学习计算机科学,专攻分布式系统和人工智能,并且还学习了哲学。90年代互联网进入德国时,他作为几家初创公司的首位编程员工。他创办过一家获风险资本投资的初创公司,在其他获得风险资本投资的快速成长的初创公司中负责架构、流程和成长挑战,曾在ImmoScout担任管理职位,并且是一家eBay Inc.公司的CTO。在他的妻子成功出售了她的初创公司后,他们搬到了海边,斯蒂芬开始从事CTO辅导工作。你可以在LinkedIn上找到他,或者在Twitter上关注@KingOfCoders。


译者评论

译者:冯若航,创业者与 PostgreSQL 专家,下云倡导者,开源 PG RDS 替代,开箱即用的 PostgreSQL 发行版 —— Pigsty 作者。

使用 Postgres 完成一切工作并不是一种空想,而是一种正在流行起来的最佳实践。对此我感到非常欣慰:早在 2016 年时我便看到了这里的潜力[12]并选择躬身入局,而事情的发展正如所愿。

我曾任职的探探,便是这条道路的先锋 —— PostgreSQL for Everything。这是一个由瑞典创始团队打造的中国互联网 App —— 使用 PostgreSQL 的规模与复杂度在中国首屈一指。探探的技术架构选型参照了 Instagram —— 或者说更为激进,几乎所有业务逻辑都使用 PostgreSQL 存储过程实现(甚至包括 100ms 的推荐算法!)。

探探整个系统架构围绕 PostgreSQL 而设计并展开。几百万日活,几百万全局 DB-TPS,几百 TB数据的量级下,数据组件只用了 PostgreSQL 。直到接近千万日活,才开始进行架构调整引入独立的数仓,消息队列和缓存。在 2017 年,我们甚至没有使用 Redis 缓存,250万 TPS 完全是由一百多台服务器上的 PostgreSQL 直接扛下的。消息队列也是用 PostgreSQL 实现的,早中期的数据分析也是由一套十几TB的专用PG集群负责。我们早已经践行了 —— “一切皆用 PostgreSQL 的理念”,并从中获益良多。

这个故事还有下半段 —— 随后的 “微服务改造” 带来了海量的复杂度,最终让系统陷入泥潭。这让我从另一个角度更加确信这一点 —— 我非常怀念一切皆用 PostgreSQL 时那种简单可靠高效敏捷的状态。


PostgreSQL 并不是一个简单的关系型数据库,而是一个数据管理的抽象框架,具有囊括一切,吞噬整个数据库世界的潜力。在十年前,这仅仅是一种潜力与可能性,在十年后,它已经兑现成为真正的影响力。而我很高兴能见证这个过程,并推动这一进程。

PostgreSQL is for Everything!


参考阅读

PGSQL x Pigsty: 数据库全能王来了

PG生态新玩家ParadeDB

FerretDB:假扮成MongoDB的PostgreSQL

AI大模型与向量数据库 PGVECTOR

PostgreSQL 到底有多强?

PostgreSQL:世界上最成功的数据库

为什么PostgreSQL是最成功的数据库?

为什么说PostgreSQL前途无量?

更好的开源RDS替代:Pigsty

References

PG生态新玩家:ParadeDB

微信公众号原文链接


PG生态新玩家ParadeDB

YC S23 投了一个新项目 ParadeDB, 非常有意思。他们的 Slogan 是 “Postgres for Search & Analytics —— Modern Elasticsearch Alternative built on Postgres”。就是用于搜索和分析的 PostgreSQL,旨在成为 Elasticsearch 的替代。

PostgreSQL 的生态确实越来越繁荣了,在基于 PG 的扩展与衍生中,我们已经有了基于 MongoDB 开源替代 —— FerretDB,SQL Server 开源替代 Babelfish,Firebase 开源替代 Supabase,AirTable 开源替代 NocoDB,现在又多了 ElasticSearch 开源替代 —— ParadeDB。

ParadeDB 实际上是由三个 PostgreSQL 扩展组成:pg_bm25pg_analytics,以及 pg_sparse。这三个扩展都可以独立使用了。我已经将这几个扩展打好包(v0.5.6),并将会在 Pigsty 的下个 Release 中默认收录,让用户能够开箱即用。

我翻译了 ParadeDB 的官网介绍与四篇博客文章,为您介绍这个 PostgreSQL 生态的新星。 今天是第一篇 —— 概览


ParadeDB

我们荣幸地向您介绍 ParadeDB:针对搜索场景优化的 PostgreSQL 数据库。ParadeDB 是第一个旨在成为 Elasticsearch 替代的 Postgres 数据库构建,被设计为可以在PG表上进行闪电般快速的全文检索、语义检索、以及混合检索。

ParadeDB解决什么问题?

对于许多组织而言,搜索依然是一个未解问题 —— 尽管有像 Elasticsearch 这样的巨头存在,但大多数与其打过交道的开发者都知道,运行、调优和管理 Elasticsearch 是多么痛苦的一件事。虽然也有其他的搜索引擎服务,但在现有数据库上粘连对接这些外部服务,会引入更多重建索引和数据复制的复杂难题与成本。

那些追求统一权威数据源与搜索引擎的开发者转了 Postgres,PG 已经通过 tsvector 提供了基本的全文检索能力,也通过 pgvector 提供了向量语义检索能力。这些工具也许对于简单用例和中等大小的数据集来说很好使,但当表变大或查询变得复杂时就有些不够用了:

  1. 大表上的排序和关键词搜索非常缓慢
  2. 不支持 BM25 计算
  3. 没有混合检索支持,将向量搜索与全文搜索的技术
  4. 没有实时搜索 — 数据必须手动重新索引或重新嵌入
  5. 对复杂查询如分面或相关性调优的支持有限

到目前为止,我们已经目睹了许多工程团队用很勉强的方式在 Postgres 上叠加了一套 Elasticsearch,随即因为后者太过于臃肿、昂贵或复杂,而最终放弃。我们在想:如果 Postgres 本身就带有 ElasticSearch 水平的搜索会发生什么?那么开发者就不会有这种两难选择了 —— 统一使用 PostgreSQL 但搜索能力受限,还是使用事实源和搜索引擎两种独立的服务?

ParadeDB适用于谁?

Elasticsearch 拥有广泛的应用场景,但我们并不企图一蹴而就地覆盖所有场景——至少现阶段不是。我们更倾向于专注于一些核心场景 —— 专为那些希望在 PostgreSQL 上进行搜索的用户服务。对于以下情况,ParadeDB 会是您的理想选择:

  • 希望使用单一 Postgres 作为事实来源,厌恶在多个服务之间搬运复制数据。
  • 希望在不损害性能与可伸缩性的前提下,对存储在 Postgres 中的海量文档进行全文搜索。
  • 希望 ANN/相似度搜索与全文搜索相结合,从而获得更精准的语义匹配效果

ParadeDB产品介绍

ParadeDB 是一个完全托管的 Postgres 数据库,具有在任何其他 Postgres 提供者中未发现的索引和搜索 Postgres 表的能力:

特性 描述
BM25全文搜索 支持布尔、模糊、提升和关键字查询的全文搜索。搜索结果使用 BM25 算法打分。
分面搜索 Postgres 列可以定义为分面,以便轻松分桶和收集指标。
混合搜索 搜索结果可以打分,综合考虑语义相关性(向量搜索)与全文相关性( BM25)。
分布式搜索 表可以进行分片,以便进行并行查询加速。
生成式搜索 Postgres 列可以输入到大型语言模型(LLMs)中,用于自动摘要、分类或文本生成。
实时搜索 文本索引和向量列自动与底层数据保持同步。

与 AWS RDS 等托管服务不同,ParadeDB 是一个 PostgreSQL 扩展插件,不需要任何设置,可以与整个 PG 生态集成,并完全可定制。ParadeDB 是开源的(AGPLv3),并提供了一个简单的 Docker Compose 模板以满足需要自建/定制的开发者的需求。

ParadeDB 的构建方式

ParadeDB 的核心是一个带有自定义扩展的标准 Postgres 数据库,这些扩展使用 Rust 编写,引入了增强的搜索能力。

ParadeDB 的搜索引擎基于 Tantivy 构建,Tantivy 是受 Apache Lucene 启发的开源 Rust 搜索库。其索引作为原生的 PG 索引存储在PG中,从而避免了繁琐的数据复制/ETL工作,并同时可以确保事务 ACID。

ParadeDB 为 Postgres 生态提供了一个新扩展:pg_bm25pg_bm25 使用 BM25 评分算法在 Postgres 中实现了基于 Rust 的全文搜索。ParadeDB 会预装这个扩展插件。

下一步是什么?

ParadeDB 的托管云版本目前处于 PrivateBeta 阶段。我们的目标是在 2024 年初推出一个自助服务的云平台。如果你想在此期间访问 PrivateBeta 版本,欢迎加入我们的等待名单

我们核心团队的重点是开发 ParadeDB 的开源版本,将在 2023 年冬季推出。

我们 Build in Public,并很高兴能与整个社区分享 ParadeDB。欢迎关注我们,在未来的博文中我们会进一步详细介绍 ParadeDB 背后的有趣技术挑战。

令人惊叹的PostgreSQL可伸缩性

原文:Cloudflare是如何用15个PG集群支持55M QPS的 | 微信公众号原文

本文概述了 Cloudflare 是如何利用 15 个 PostgreSQL 集群,伸缩到支持每秒 5500 万个请求。

2009年7月,美国加州,一个创业团队搞了一个名为 Cloudflare 的内容分发网络(CDN),用于加速互请求,让网络访问更稳定且更快捷。他们在发展初期面临着各种挑战,然而其增长速度却十分惊人。

Overall Internet Traffic; PostgreSQL Scalability

互联网流量全局概览

现在他们承载着 20% 的互联网流量,每秒 5500 万个 HTTP 请求。 而他们仅仅使用 15 个 PostgreSQL 集群就做到了这一点。

Cloudflare 使用 PostgreSQL 来存储服务元数据,并处理 OLTP 工作负载。然而在同一个集群支持有着多种不同负载类型的租户是一个难题。一个**集群(Cluster)是一组数据库服务器,一个租户(tenant)**是特定用户或用户组专用的隔离数据空间。

PostgreSQL的可伸缩性

以下是他们如何将 PostgreSQL 的可伸缩性用到极致的。

1. 争用

大多数客户端都会相互争用 Postgres 连接。但是 Postgres 连接的成本很高,因为每个连接都是操作系统级别的独立进程。而且每个租户都有独特的工作负载类型,所以很难创建一个全局阈值进行限流。

而且,人工限制行为不端的租户是一项巨大的工作。某个租户可能会发起一个开销巨大的查询,因而阻塞邻居租户的查询饿着他们。同时,一旦查询到达数据库服务器这儿,再想隔离它就很难了。

Connection Pooling With PgBouncer

使用 Pgbouncer 进行连接池化

因此他们使用 Pgbouncer 作为 Postgres 前面的连接池。PgBouncer 将充当 TCP 代理,池化 Postgres 连接。租户连接到 PgBouncer ,而不是直连 Postgres。因而限制了 Postgres 连接的数量,也能防止连接饥饿现象。

此外,PgBouncer 还通过使用持久连接来规避了创建和销毁数据库连接的高昂开销,也被用于在运行时限流那些发起高开销查询的租户们。

2. 惊群

当许多客户端同时查询服务器时就会出现**惊群(Thundering Herd)**的问题,这会导致数据库性能降级。

Thundering Herd Problem

惊群

当应用程序被重新部署时,其状态会初始化,应用会一次性创建许多条数据库连接。因而当当租户争抢 Postgres 连接时,就会引起惊群现象,Cloudflare 使用 PgBouncer 来限制特定租户创建的 Postgres 连接数。

3. 性能

Cloudflare 没有在云上运行 PostgreSQL ,而是使用没有任何虚拟化开销的裸金属物理机,以实现最好的性能。

Load Balancing Traffic Between Database Instances

在数据库实例之间对流量做负载均衡

Cloudflare 使用 HAProxy 作为四层负载均衡,Pgbouncer 将查询转发至 HAProxy,而 HAProxy 负载均衡器会在集群主实例与只读副本之间对流量进行负载均衡。

4. 并发

如果有许多租户发起并发(Concurrent)查询,性能会下降。

Congestion Avoidance Algorithm Throttling Tenants

拥塞控制限流算法

因而 Cloudflare 使用 TCP Vegas 拥塞控制算法 来对租户限流。这个算法的工作原理是,首先采样每个租户的事务往返 Postgres 的响应时间(RTT),然后只要 RTT 不降级就持续调整连接池大小,因而在出现资源枯竭前就能实现限流。

5. 排队

Cloudflare 在 PgBouncer 层面使用队列对查询进行排队。查询在队列中的顺序取决于它们的历史资源使用情况,换句话说,需要更多资源的查询会排在队列的尾部。

Ordering Queries in Priority Queue

使用优先队列排序查询

Cloudflare 只在流量峰时刻启用优先队列以防资源饥饿。换言之在正常流量中,查询不会永远排在队尾。

这种方法改善了绝大多数查询的延迟(Latency),不过在流量峰时发起大开销查询的租户会观察到更高的延迟。

6. 高可用

Cloudflare 使用 Stolon 集群管控负责 Postgres 的高可用.

High Availability of Data Layer With Stolon

使用 Stolon 负责数据库高可用

Stolon 可用于搭建 Postgres 主从复制,并在出现问题时负责选举 Postgres 集群领导者(主库)并进行故障切换。

这里的每个数据库集群都会复制到两个区域,每个区域内有三个实例。

写请求会被路由到主要区域中的主库上,然后异步复制到次要区域,读请求会路由到次要区域中处理。

Cloudflare 会进行组件间连通性测试以便主动发现网络分区问题,也会进行混沌测试以优化系统韧性,还会配置冗余的网络交换机于路由器来避免网络分区。

当故障切换结束,主库实例重新上线时,他们会使用 pg_rewind 工具重放错过的写入变更,来让旧主库重新与集群同步。

Cloudflare 的 Postgres 主库实例与从库实例加起来超过 100 台。他们组合使用了 操作系统资源管理,排队理论,拥塞控制算法,甚至是 PostgreSQL 统计量来实现 PostgreSQL 的可伸缩性。

评价与讨论

这是一篇有价值的经验分享,主要介绍了如何使用 Pgbouncer 以解决 PostgreSQL 的可伸缩性(Scalability)问题。五千万 QPS + 20% 的互联网流量,听上去是不小的一个规模。尽管从 PostgreSQL 专家的角度看这里的实践确实写的有些朴素简陋,但是这篇文章确实抛出来了一个有意义的问题 —— PostgreSQL的 可伸缩性

PostgreSQL 的可伸缩性现状

PostgreSQL 在垂直伸缩和水平伸缩能力上享有盛誉。在读请求上,PostgreSQL 没有什么伸缩性问题 —— 因为读写互不阻塞,所以只读查询的吞吐量上限几乎是随投入的资源(CPU)线性增长的,无论是垂直增加 CPU/内存还是水平扩容拖从库,都可以通过加资源解决。

PostgreSQL 在写入上的伸缩性没有读上那么强,单机 WAL 写入/重放速度达到 100 MB/s ~ 300 MB/s 就会遇到软件瓶颈 —— 但对于常规生产 OLTP 负载这已经是一个很大的值了 —— 作为参考,探探这样一个两亿用户千万日活的应用,所有数据库写入的结构化数据率就在 120 MB/s 左右。PostgreSQL 社区也正在讨论通过 DIO/AIO 以及并行WAL重放的方式来进一步拓展此瓶颈。用户也可以考虑使用 Citus 或者其他分库分表中间件实现写入的伸缩扩容。

在容量上,PostgreSQL 的可伸缩性主要取决于磁盘,本身并没有瓶颈。在 NVMe SSD 单卡64TB的当下,配合压缩卡支持百TB级别的数据容量毫无问题,更大的容量也可以使用 RAID 或使用多个表空间的方式进行支持。社区曾经报告不少百TB量级的OLTP实例,也有零星 PB 级的实例。大实例的挑战主要是备份管理与空间维护上的,而不是性能上的。

在过去,PostgreSQL 可伸缩性比较为人诟病的一个问题,就是对海量连接的支持 (在 PostgreSQL 14 后得到显著改善)。PostgreSQL 和 Oracle 默认的模型一样都使用了多进程架构。这种设计有着更好的可靠性,但在面对海量高并发场景时,这种模型就有些拖后腿了。

互联网场景下数据库访问模式主要是海量短连接:一个查询过来就创建一条连接,执行完后就销毁连接 —— PHP 以前就是这么干的,所以和使用线程模型的搭档 MySQL 很配。但对于 PostgreSQL 而言,海量的后端进程与频繁的进程创建销毁会浪费大量的软硬件资源,因而在这种场景的性能表现上就些力不从心了。

连接池 —— 解决高并发问题

PostgreSQL 推荐默认使用的连接数量约为 CPU 核数的两倍,通常在几十 ~ 几百的范围内会比较合适。互联网场景下动辄以千/以万计的客户端连接如果直连 PostgreSQL,就会产生显著的额外负担。连接池便是为了解决这个问题而出现的 —— 可以说,连接池对于在互联网场景下使用 PostgreSQL 是一个必选项,能够起到化腐朽为神奇的效果。

请注意,PostgreSQL 并非不支持高吞吐,问题的关键在于并发连接的数量 —— 在《PG性能有多强》中,我们在 92 vCPU 的服务器上使用 约 96 条连接压测出 sysbench 点查吞吐量峰值 233 万。而在超出可用资源后,这一最大吞吐随着并发进一步加大而开始缓慢下降。

使用连接池有一些显著的好处:首先,数万条客户端连接,可以池化缓冲收敛为几条活跃 Server 连接(使用事务级连接池),极大减少了操作系统上的进程数量与开销,也避免了进程创建销毁的开销。第二点,并发争用的情况因为活跃连接数的减少而大大减小,进一步优化了性能。第三点,突然出现的负载峰值会在连接池上排队,而不是直接打爆数据库,降低了雪崩概率,从而提高了系统的稳定性。

性能与瓶颈

我在探探时有很多关于 PgBouncer 的最佳实践,我们有一套核心数据库集群,整个集群有着 50万 QPS,主库上的客户端连接数为两万,写入 TPS 约为 5 万。这样的负载如果直接打到 Postgres 上会立即打爆数据库。因此在应用与数据库之间,还有一个 PgBouncer 连接池中间件。所有两万条客户端连接经过连接池事务池化模式后,总共只需要 5 ~ 8 条活跃服务器连接就支撑起所有的请求,CPU 使用率约为 20%,这是一个非常巨大的性能改善。

PgBouncer 是一个轻量级连接池,可以部署在用户侧或者数据库侧。PgBouncer 本身因为使用了单进程模式,存在一个 QPS / TPS 瓶颈,约为 3 ~ 5 万。因此为了避免 PgBouncer 本身的单点问题与瓶颈,在核心主库上我们使用了 4 个幂等的 PgBouncer 实例,并通过 HAProxy 均匀分发流量给这四个 PgBouncer 连接池池化后,再到数据库主库上处理。但是对于绝大多数场景而言,单个 PgBouncer 进程的 3万 QPS 的处理能力已经是绰绰有余了。

管理灵活性

PgBouncer 的一个巨大优势是,它可以提供 User / Database / Instance 级别的查询响应时间指标(RT)。这是用于性能衡量的核心指标,对于早些年的 PostgreSQL 老版本,PgBouncer 中的统计值也是获取这类数据的唯一方式。尽管用户可以通过 pg_stat_statements 扩展获取查询组的 RT, PostgreSQL 14 以后也可以获取数据库级别的会话活跃时间来计算事务 RT,新出现的 eBPF 也可以完成这一点。但 PgBouncer 提供的性能监控数据对于数据库管理仍然是非常重要的参考依据。

PgBouncer 连接池不仅提供了性能上的改善,还为精细管理提供了抓手。例如在数据库在线不停机迁移中,如果在线流量完全通过连接池访问,那么你就可以通过简单修改 PgBouncer 配置文件的方式,将旧集群的读写流量丝滑重定向到新集群中,甚至都不需要业务方即时参与改配置重启服务。你也可以像上面 Cloudflare 的例子一样,在连接池修改 Database / User 的参数,实现限流的能力。如果某一个数据库租户表现不良,影响了整个共享集群,管理员可以在 PgBouncer 上轻松实现限流与阻断的能力。

其他替代品

PostgreSQL 生态中还有其他的一些连接池产品。与 PgBouncer 同期的 PGPool-II 也曾经是一个有力竞争者:它提供了更为强大的负载均衡/读写分离等能力,也能充分利用多核的能力,但是对 PostgreSQL 数据库本身有侵入性 —— 需要安装扩展才能用,而且曾经有比较显著的性能折损(30%)。所以在连接池大PK中,简单轻量的 PgBouncer 成为了胜利者,占据了PG连接池的主流生态位。

除了 PgBouncer 之外,新的 PostgreSQL 连接池项目也在不断出现,比如 Odyssey,pgcat,pgagroal,ZQPool 等。我非常期待能有一个完全兼容 PgBouncer 的高性能/更易用原位替代出现。

此外,许多编程语言标准库的数据库驱动里,都开始内置了连接池,加上 PostgreSQL 14 的改进让多个进程的开销减少。以及硬件性能的指数增长(现在都有 512 vCPU 的服务器了,内存也不是啥稀缺资源了)。所以有时候不用连接池,几千个连接直接干上去也是一个可行选项了。

我能用上 Cloudflare 的实践吗?

随着硬件性能的不断提升,软件架构的不断优化,管理最佳实践的逐渐普及 —— 高可用、高并发、高性能(可伸缩性)对于互联网公司来说属于老生常谈,基本不算什么新鲜技术了。

例如在当下,随便一个初级 DBA / 运维,只要使用 Pigsty 部署一套 PostgreSQL 集群都可以轻松做到这一点,包括 Cloudflare 提到的 Pgbouncer 连接池,以及高可用组件 Stolon 的上位替代 Patroni ,都已经做到开箱即用了。只要硬件达标,轻松处理好海量并发百万请求不是梦。

在本世纪初,一台 Apache 服务器只能处理很可怜的一两百个并发请求。最优秀的软件也很难处理上万的并发 —— 业界有个著名的 C10K 高并发 问题,谁要是能做到几千并发,那就是业界高手。但随着 Epoll 和 Nginx 在 2003/2004 年相继问世,“高并发” 不再是什么难题了 —— 随便一个小白只要学会配置 Nginx,就可以达到前几年大师们做梦都不敢想的程度 —— 瑞典马工《云厂商眼中的客户:又穷又闲又缺爱

这就跟现在随便哪个新手都可以拿 Nginx 实现以前用 httpd 的大师们想都不敢想的 Web 海量请求与高并发一样。PostgreSQL 的可伸缩性也随着 PgBouncer 的普及走入千家万户。

例如,在 Pigsty 中,默认为所有 PostgreSQL 1:1 部署了 PgBouncer 实例,使用事务池化模式,并纳入监控。而默认的 Primary 与 Replica 服务也是通过 PgBouncer 访问 Postgres 数据库的。用户不需要操心太多与 PgBouncer 有关的细节 —— 例如, PgBouncer 的数据库与用户是在通过剧本创建 Postgres 数据库/用户时自动维护的。一些常见的配置注意事项和坑也在预置配置模板中进行了规避,力求做到开箱即用。

当然,对于非互联网场景的应用,PgBouncer 也并非必须品。而且默认的 Transaction Pooling 虽然在性能上非常优秀,但也是以牺牲了一些会话级功能为代价的。所以您也完全可以配置 Primary / Replica 服务直连 Postgres,绕过 PgBouncer;或者使用兼容性最好的 Session Pooling 模式。

总的来说,PgBouncer 确实是一个非常实用的 PostgreSQL 生态工具。如果您的系统对于 PostgreSQL 客户端并发连接数有着较高要求,那么在测试性能时请务必试一试这款中间件。

展望 PostgreSQL 的2024

微信公众号原文

本文是 PostgreSQL 核心组成员 Jonathan Katz 对 2024 年 PostgreSQL 项目的未来展望,并回顾过去几年 PostgreSQL 所取得的进展。

作者:Jonathan Kats,Amazon RDS 首席产品经理兼技术主管, PostgreSQL 全球开发组核心成员与主要贡献者。博客:https://jkatz05.com/。

译者:冯若航 / Vonng。磐吉云数创始人 / CEO,PostgreSQL 专家与布道师,开源 RDS PG —— Pigsty 作者。博客:https://vonng.com

点击“查看原文”查看英文原文:https://jkatz05.com/post/postgres/postgresql-2024/

在我经常听到的问题中,有一个尤为深刻:“PostgreSQL 将走向何方?” —— 这也是我经常问自己的一个问题。这个问题不仅仅局限在数据库内核引擎的技术层面,而关乎整个社区的方方面面 —— 包括相关的开源项目、活动和社区发展。PostgreSQL 已经广受欢迎,并且已经是第四次被 DB Engine评为“年度数据库。尽管已取得显著成功,我们依然需要不时地后退一步,从更宏观的角度思考 PostgreSQL 的未来。虽然这种思考不会立即带来显著的变化,但它对于社区正在进行的工作提供了重要的背景板。

新年是思考 **“PostgreSQL 的未来”**这一问题的绝佳时机,我对2024年的PostgreSQL发展方向也有一些思考,这里是我的一些想法:这并不是一个路线图,而是我个人对 PostgreSQL 发展方向的一些想法。


PostgreSQL功能开发

PGCon 2023 开发者会议上,我提出了一个题为“PostgreSQL 用户面临的重大挑战是什么?”的话题。这个话题旨在探讨用户的常见需求和数据库工作负载的发展趋势,以此来判断我们是否正在朝着正确的方向发展 PostgreSQL。通过多次交谈和观察,我提出了三个主要的特性类目:

  • 可用性
  • 性能
  • 面向开发者的特性

这些特性组将成为 2024 年,甚至更长时间段里的工作重点。接下来,我将对每个特性类目进行更深入的探讨。

可用性

对于PostgreSQL现有用户和潜在用户来说,提高可用性是最迫切的需求。这个需求不仅仅是排在第一位,而且毫不夸张地讲,也同时能排在第二位和第三位。虽然重启 PostgreSQL 通常可以迅速完成,但在某些极端情况下,这个过程可能耗时过长。此外,长时间的写入阻塞,例如某些锁操作,也可被视作一种“停机时间”。

大部分 PostgreSQL 用户对现有的可用性水平已感满意,但有些工作负载对可用性的要求极为严格。为了更好地满足这些要求,我们需要进行额外的开发工作。这篇文章或这一小节就聚焦于这一点:通过改进使 PostgreSQL 适用于更多有严苛可用性需求的环境。

逻辑复制是如何助益于双主,蓝绿部署,零停机升级,以及其他工作流的

对于现有的 PostgreSQL 用户,以及那些计划迁移至 PostgreSQL 的用户来说,提升可用性是最重要的需求。这通常指的是高可用——即在计划内的更新或计划外的中断期间,数据库能够持续进行读写操作的能力。PostgreSQL 已经提供了许多支持高可用的特性,如流复制。然而为了实现最高水平的可用性,通常还需要借助额外的服务或诸如 Patroni 这样的工具。

我聊过许多用户,在绝大多数情况下,他们对 PostgreSQL 提供的可用性是满意的。但我也发现了一个新趋势:现在有一些负载对可用性的要求越来越高,15-30 秒的离线窗口已不够了。这包括计划内的中断(如小版本升级、大版本升级),以及计划外的中断。一些用户表示,他们的系统最多只能承受1秒的不可用时间。起初我对这种要求持怀疑态度,但了解到这些工作负载的具体用途后,我认为1秒确实是一个合理的需求。

在持续提高 PostgreSQL 可用性方面,逻辑复制 是一个关键特性。逻辑复制能够实时将 PostgreSQL 数据库中的变更流式传输到任何支持 PostgreSQL 逻辑复制协议的系统中。PostgreSQL 中的逻辑复制已经存在了一段时间,而最近的版本在可用性方面带来了显著的改进,包括功能和性能上的新特性。

逻辑复制在 PostgreSQL 的大版本升级过程中扮演着关键角色,与传统的物理(或二进制)复制相比,它的一大优势在于能够实现跨版本的数据流转。举例来说,通过逻辑复制,我们可以轻松地将 PostgreSQL 15 的数据变更实时传输至 PostgreSQL 16,从而大幅缩减升级过程中的停机时间。这种方法已在 Instacart 的零停机大版本升级中得到成功应用。然而,PostgreSQL 在支持此类用例和其他高可用性场景方面仍有待提升。未来的发展预计将进一步优化支持蓝绿部署的功能,以实现更加无缝的数据迁移和应用升级。

除了在大版本升级中的用例,逻辑复制本身也是构建高可用系统的重要手段。"多主复制“就是其中的一个典型应用,它允许多个数据库实例同时接受写入操作,并在它们之间同步数据变更。这种模式尤其适用于对停机时间敏感的系统(例如:不接受1秒以上的不可用时间),其设计目标是在任何写入数据库出现问题时,应用能迅速切换到另一可用的写入数据库,而不必等待它被提升为新主库。构建与管理这样的双活系统是极度复杂的:它会影响到应用设计,并需要用户提供对写入冲突进行管理的策略,而且为了确保数据完整性(比如:冲突风暴),需要有仔细设计的容错监控系统 —— (比如,一个实例如果几个小时都无法复制它的变更会发生什么?)

大版本升级和双活复制案例为我们指明了改善 PostgreSQL 逻辑复制的方向。Amit Kapila 是众多逻辑复制功能开发的领导者。今年,他和我共同在一场会议上发表了题为“PostgreSQL 中的多主复制之旅”的演讲(并提供了视频版本),深入探讨了为何针对这些用例的解决方案至关重要、PostgreSQL 在逻辑复制方面取得的成就,以及为更好支持这些场景所需做的工作。好消息是从 PostgreSQL 16 版本起,我们已经有了大部分基础模块来支持双活复制、蓝绿部署和零停机大版本升级。虽然这些功能可能没有全部集成在内核中,但某些扩展(比如我参与开发的pgactive)已提供了这些能力。

在 2024 年,有多项努力旨在帮助缩小这些功能差距。对于 PostgreSQL 17 来说(惯例免责声明:这些特性可能不会发布),有一个重点是确保逻辑复制能够与关键工作流(如pg_upgrade高可用系统)协同工作,支持更多类型的数据变更(如序列/Sequence)的复制,扩展对更多命令(如 DDL)的支持,提高性能,以及增加简化逻辑复制管理的特性(如节点同步/再同步)。

这些努力能让 PostgreSQL 适用于更多种类的负载,特别是那些有着极致严苛可用性要求的场景,并简化用户在生产环境中滚动发布新变更的方式。尽管改进逻辑复制功能的道路仍然漫长,但 2024 年无疑将为 PostgreSQL 带来更多强大的功能特性,帮助用户在关键环境中更加高效地运行 PostgreSQL。

减少锁定

另一个有关可用性的领域是模式维护操作(即DDL语句)。例如,ALTER TABLE的大部分形式会对表施加 ACCESS EXCLUSIVE 锁,从而阻止对该表的所有并发访问。对于许多用户来说这等同于不可用,即使这只是数据的一个子集。PostgreSQL 缺乏对非阻塞/在线模式维护操作的完整支持,随着其他关系数据库也开始支持这些功能,这方面的不足开始逐渐凸显。

目前虽有多种工具和扩展支持非阻塞模式更新,但如果 PostgreSQL 能原生支持更广泛的非阻塞模式变更,那肯定更方便,而且性能也会更好。从设计上来看,我们已有了开发此功能的基础,但还需要一些时间来实现。尽管我不确定是否有正在进行中的具体实现,但我相信在2024年我们应该在这方面取得更多进展:让用户能够在不阻塞写入的情况下执行大部分(或全部)DDL 命令

性能

性能是一个不断持续演进的特性 —— 我们总是会追求更快的速度。好消息是,PostgreSQL 在垂直扩展能力上享有盛誉 —— 当你为单个实例提供更多硬件资源时,PostgreSQL 也能扩展自如。虽然在某些场景下,水平扩展读写操作是有意义的。但我们还是要确保 PostgreSQL 能够随着计算和内存资源的增加而持续扩展。

举个更具体的例子:考虑到 AWS EC2 实例中有着高达 448 vCPU / 24TB 内存 的选配项 —— PostgreSQL 能否在单个实例上充分利用这些资源呢?我们可以根据 PostgreSQL 用户现在与未来可能使用的硬件配置,设定一个性能提升的目标,并持续提升 PostgreSQL 的整体表现。

在 2024 年,已经有多项工作致力于继续垂直扩展 PostgreSQL。其中最大的努力之一,也是一个持续多年的项目,就是在 PostgreSQL 中支持 DirectIO(DIO)与 Asynchronous IO(AIO)。至于细节我就留给 Andres Freund 在PGConf.EU上关于在 PostgreSQL 中添加 AIO 的现状的PPT来讲了。看起来在 2024 年,我们将离完全支持 AIO 更进一步。

另一项让我感兴趣的工作是并行恢复。有着大量写入负载的 PostgreSQL 用户往往会推迟 Checkpoint 以减少 I/O 负载。对于忙碌的系统而言,如果 PostgreSQL 在执行 Checkpoint 的相当一段时间后才崩溃,那么当 PostgreSQL 重新启动时,它会进入 “崩溃恢复 “状态:它会重新执行自上次 Checkpoint 以来的所有变更,以便达到一致的状态 —— 在崩溃恢复期间,PostgreSQL 不能读也不能写,这意味着它不可用。这对繁忙的核心系统来说是个问题:虽然 PostgreSQL 可以接受并发写入,但它重放变更时只能使用单个进程。如果一个繁忙系统崩溃于上个检查点后的一小时,那么系统会需要离线追赶几个小时,才能达到一致的状态点重新上线!

克服这一局限性的方法之一是支持”并行恢复",或者说能够并行重放WAL变更。在PGCon 2023上,Koichi Suzuki做了一个 关于PostgreSQL如何支持并行恢复 的详细介绍。这不仅适用于崩溃恢复,也适用于任何 PostgreSQL WAL 重放操作(例如:PITR 时间点恢复)。虽然这是一个极具挑战性的问题,但支持并行恢复有助于 PostgreSQL 继续垂直扩展,因为用户可以进一步针对重度写入负载进行优化,也能缓解 “从故障中恢复上线所需的延时超出承受范围” 的风险。

这并不是一份关于性能特性的详细清单。在 PostgreSQL 服务器性能上还有很多工作要做,包括索引优化、改进锁机制、充分利用硬件加速等。此外,客户端(如驱动程序和连接池)上的工作也能为应用与 PostgreSQL 的交互带来额外的性能提升。展望 2024 年,看看社区正在进行的工作,我相信 PostgreSQL 在各个领域上的性能都会有整体性提升。

开发者特性

我认为 “开发者特性 “(developer features)是一个相当宽泛的类目,核心在于如何让用户围绕 PostgreSQL 来架构 & 构建应用。这里包括:SQL语法、函数、存储过程语言支持,以及帮助用户从其他数据库系统迁移到 PostgreSQL 的功能。一个具体的创新例子是在 PostgreSQL 14 中引入的 multirange 数据类型,它允许用户将一些不连续的 范围(Range) 聚合在一起,这个特性非常实用,我个人在实现一个调度功能时,用它将数百行PL/pgSQL代码减少到三行。开发者特性也关乎 PostgreSQL 如何支持新出现的工作负载:例如JSON 或向量

值得一提的是,许多开发者特性创新主要出现在**扩展(Extension)**上,而这正是 PostgreSQL 可扩展模型的优势所在。然而就数据库服务器本身而言,PostgreSQL 在某些开发者特性上的发布速度相比过去有所落后。例如,尽管PostgreSQL是第一个将JSON作为可查询数据类型的关系数据库,但它在实现 SQL/JSON 标准锁定义的语法与特性上已经开始变得迟缓。PostreSQL 16 发布了 SQL/JSON 中的一些语法特性,2024 年也会有更多的努力用在实现 SQL/JSON 标准上。

话既然说到这儿了,我们应当着力于 PostgreSQL 中那些无法通过扩展插件实现的开发者特性,比如 SQL标准特性。我的建议是集中精力关注那些其他数据库已经具备的功能,比如进一步实现 SQL/JSON 标准(例如: JSON_TABLE)、系统层面的版本化表(对于审计、闪回,与在特定时间点进行的时态查询非常有用),以及对模块的支持(对于“打包”存储过程来说尤其重要)。

此外,考虑到之前讨论的可用性和性能问题,我们应继续努力简化用户从其他数据库迁移到 PostgreSQL 的过程。在我的日常工作中,我有机会了解了大量与数据库迁移相关的内容:从商业数据库到 PostgreSQL 的迁移策略。当我们增强 PostgreSQL 功能的同时,也有许多机会可以简化迁移流程。包括引入其他数据库中现有的功能(例如全局临时表、全局分区索引、自治事务),并在 PL/pgSQL 中增加更多功能与性能优化(如批量数据处理函数、模式变量缓存函数元数据)。所有这些都将改善 PostgreSQL 开发者的体验,并让其他关系数据库的用户更容易采纳 PostgreSQL。

最后我们需要了解,如何才能持续不断地支持来自 AI/ML 数据的新兴负载,特别是向量存储与检索。在2023年的PGCon会议上,尽管人们希望在 PostgreSQL 本身中看到原生的向量支持,但大家一致认为,在 pgvector这样的扩展中实现这类功能可以抢占先机,更快地支持这些工作负载(这一策略似乎已经奏效在向量数据上性能表现优异)。有鉴于向量负载的诸多特征,我们可以在PostgreSQL中添加一些额外的支持,以便进一步支持它们:其中包括对处理 活动查询路径中的TOAST数据的规划器进行优化,并探索如何更好地支持带有大量过滤条件和 ORDER BY 子句的查询。

我确信在 2024 年,PostgreSQL 可以在这些领域取得显著进步。我们看到在 PostgreSQL 的扩展生态中,有大量的新能力正在涌现;但即便如此,我们还是可以继续直接为 PostgreSQL 添加新特性,让它更易于构建应用。

安全性如何?

我想快速过一下 PostgreSQL 的安全特性。众所周知在安全敏感型场景中,PostgreSQL 有着极佳的声誉。但总会有许多能改进的地方。在过去几年中,PostgreSQL社区对引入透明数据加密(TDE)的原生支持表现出许多兴趣与关注。然而还有许多其他地方可以搞搞创新,比如支持其他的身份验证方式/机制(主要需求是OIDC),或是探索联邦授权模式的可能性,使PostgreSQL能够继承其他系统的权限设置。尽管这些特性在当下都颇有挑战,我建议先在 “Per-Database” 层面上支持 TDE。这里我不想过多展开,因为已经有在 PostgreSQL 中满足这些特性需求的方法了,但我们还是应该不懈努力,争取实现完整的原生支持。

让我们再来看看PostgreSQL能在2024年里发力的其他方向。


扩展

PostgreSQL 的设计是高度可扩展的。您可以为PostgreSQL添加新功能,而无需分叉项目。包括新的数据类型、索引方法、与其他数据库系统协同工作的方法、更易于管理PostgreSQL特性的实用工具、额外的编程语言支持,甚至编写自己的扩展插件。人们已经围绕一些特定的 PostgreSQL 扩展(如PostGIS)建立了开源社区和公司;PostgreSQL 单一数据库便能支持不同类型的工作负载(地理空间、时间序列、数据分析、人工智能),正是扩展让这件事变得可能。数千个可用的PostgreSQL扩展成为了PostgreSQL的 “力量倍增器” —— 它一方面让用户能够快速的为数据库新增功能,另一方面也极大推动了 PostgreSQL 的普及与采用。

然而这也产生了一个副作用,即“扩展蔓延”现象。用户如何去选择合适的扩展?扩展的支持程度如何?如何判断某个扩展是否有持续积极的维护?如何为扩展做出自己的贡献?甚至“在哪里可以下载扩展”也成为了一个大问题。postgresql.org 提供了一个不完整的扩展列表,社区也维护了一些扩展包,也有其他几个可供选择的 PostgreSQL 扩展仓库(例如 PGXNdbdevTrunk)和 pgxman 可供选择。

PostgreSQL社区的一个优势是去中心化,广泛散布于世界各处。但我们可以做得更好,帮助用户在复杂的数据管理中做出明智的选择。我认为2024年是一个机遇,我们可以投入更多资源来整合与展示 PostgreSQL 扩展,帮助用户理解什么时候可以使用哪些扩展,并了解扩展们的开发成熟度,并同样为扩展开发者提供更好的管理支持与维护资源。


社区建设

在谈论2024年社区建设的构想时,我深感自加入 PostgreSQL 贡献者社区以来,我们已取得显著进步。社区在认可各类贡献者方面表现突出(尽管仍有提升空间)—— 不仅限于代码贡献,还包括项目的各个方面。展望未来,我想着重强调三个关键领域:导师制、多元化、公平与包容(DEI)以及透明度,这些都对项目的全方位发展至关重要。

PGCon 2023开发者会议上,Melanie Plageman 就新贡献者的体验和挑战进行了深入分析。她提到了诸多挑战,如初学者需要花费大量时间来掌握基本知识,包括使用代码库和邮件列表进行交流,以及将补丁提交到可审查状态所需的努力。她还指出,提供建设性指导意见(从审查补丁开始)可能比编写代码本身更具挑战性,同时也讨论了如何有效地提供反馈。

关于提供反馈,我想引用罗伯特-哈斯(Robert Haas)的一篇优秀博文,其中他特别强调了在批评时同时给予表扬的重要性——这种方法可以产生显著的效果,并提醒我们即使在批评时也应保持支持态度。

回到 Melanie 的观点,我们应该在整个社区更好地实施导师计划。就我个人而言,我认为我在宣传项目方面做得不够好,包括帮助更多人为网络基础设施发布流程 做出贡献。这并不是说 PostgreSQL 缺乏优秀的导师,而是我们可以在帮助人们开始贡献和找到导师方面做得更好。

2024年将是建立更完善导师制度的起点。我们希望在5月于温哥华举行的 PGConf.dev 2024 上试验一些新想法。

PGConf.dev 出现前,从2007年到2023年,PGCon一直是PostgreSQL贡献者们集结并讨论即将开始的开发周期和关键项目的重要活动。PGCon 一直由 Dan Langille 负责组织。经过多年的辛勤工作,他决定将组织职责扩展至一个团队,并协助成立了 PGConf.dev

PGConf.dev 是专为那些希望为 PostgreSQL 做贡献的人士举办的会议。会议内容覆盖了 PostgreSQL 的开发工作(包括内核及所有相关的开源项目,如扩展和驱动程序)、社区建设以及开源意见领袖等主题。PGConf.dev 的一大特色是导师制,并计划举办关于如何为 PostgreSQL 贡献的研讨会。如果你正寻找为 PostgreSQL 贡献的机会,我强烈建议你考虑参加本活动或提交演讲提案

接下来是 PostgreSQL 社区如何在多元化、公平与包容性(DEI)上进步的话题。我强烈建议观看凯伦·杰克斯莱蒂西亚·阿夫罗特在 2023 年 PGConf.eu 上的演讲: 在肯的 Mojo Dojo Casa House 里尝试成为芭比:因为这是一场关于如何继续让 PostgreSQL 社区变得更加包容的深刻演讲。社区在这方面取得了进步(凯伦和莱蒂西亚指出了有助于此的一些举措),但我们还能做得更好,我们应该积极主动地处理反馈,以确保为 PostgreSQL 做出贡献是一种受欢迎的体验。我们所有人都可以采取行动,例如,在发生(诸如性别歧视的)不当行为时及时指出,并指出行为不当的原因。

最后是透明度问题。在开源领域这可能听起来有些奇怪,毕竟它本身就是开放的。但有不少治理问题并不会在公开场合讨论,了解决策制定的流程会很有帮助。PostgreSQL 行为守则委员会 提供了一个优秀的例子:一个社区如何就需要敏感处理的问题保持透明度。该委员会每年都会发布一份报告(这是 2022 年的报告),包括案例的总体描述和整体统计数据。我们可以在许多 PostgreSQL 团队中复制这种做法 —— 这些团队参与的任务可能由于其敏感性需要保密。


结论:本来这篇文章应该更短

最初,我以为这篇文章会是一篇简短的帖子,几小时内就能完成。但几天后,我意识到情况并非如此……

老实说,PostgreSQL目前处于一个非常好的状态。它依然备受欢迎,其可靠性、鲁棒性和性能的声誉稳如磐石。然而我们仍可以做得更好,令人感到振奋的是,社区正在积极地在各个方向上努力改善。

虽然上面这些是 PostgreSQL 在 2024 年及以后可以做的事情,但 PostgreSQL 走到今天已经做成了很多很多的事。提出 “PostgreSQL何去何从” 这样的问题,实际上为我们提供了一个机会:回顾过去几年 PostgreSQL 所取得的进展,并展望未来!

PostgreSQL 规约(2024版)

微信公众号原文


0x00背景

没有规矩,不成方圆。

PostgreSQL的功能非常强大,但是要把PostgreSQL用好,需要后端、运维、DBA的协力配合。

本文针对PostgreSQL数据库原理与特性,整理了一份开发/运维规约,希望可以减少大家在使用PostgreSQL数据库过程中遇到的困惑:你好我也好,大家都好。

本文第一版主要针对 PostgreSQL 9.4 - PostgreSQL 10 版本 ,当前最新版本针对 PostgreSQL 15/16 进行更新与调整。


0x01 命名规范

计算机科学只存在两个难题:缓存失效和命名

通用命名规则(Generic)

  • 本规则适用于所有数据库内对象,包括:库名、表名、索引名、列名、函数名、视图名、序列号名、别名等。
  • 对象名务必只使用小写字母,下划线,数字,其中首字母必须为小写字母。
  • 对象名长度不得超过63个字符,命名统一采用 snake_case 风格。
  • 禁止使用SQL保留字,使用select pg_get_keywords(); 获取保留关键字列表。
  • 禁止出现美元符号 $ ,禁止使用中文,不要以 pg 开头。
  • 提高用词品味,做到信达雅;不要使用拼音,不要使用生僻冷词,不要使用小众缩写。

集群命名规则 (Cluster)

  • PostgreSQL 集群的命名将作为集群资源的命名空间,必须为有效的 DNS 域名,不包含任何点号与下划线。
  • 集群名应当由小写字母开头,仅包含小写字母、数字、减号,符合正则表达式:[a-z][a-z0-9-]*
  • PostgreSQL 数据库集群命名通常以三段式结构:pg-<biz>-<tld>。数据库类型 / 业务名称 / 业务线或环境
  • biz 为最能代表业务特征的英文词语,应当仅由小写字母与数字组成,不得包含连字符 -
  • 使用备份集群搭建某一个现有集群的延迟从库时,biz 名应当为 <biz>delay,例如 pg-testdelay
  • 分支一个现有集群时,可以在 biz 尾部添加数字:例如从 pg-user1 可以分支出 pg-user2pg-user3
  • 水平分片集群,biz命名中应当包含 shard,并缀以分片号,例如 pg-testshard1pg-testshard2,……
  • <tld> 为顶层业务线,也可用于区分不同环境:例如 -tt-dev-uat-prod 等。无此需要可以省略。

服务命名规则(Service)

  • 每一套 PostgreSQL 集群会对外提供 2~6 种不等的服务,这些默认使用固定命名规则。
  • 服务名以集群名作为前缀,服务类型作为后缀,例如 pg-test-primarypg-test-replica
  • 读写服务统一以 primary 后缀命名,只读服务统一以 replica 后缀命名,这两个为必选服务。
  • ETL拉取/个人用户查询以 offline 后缀命名,直连主库/ETL写入以 default 后缀命名,为选配服务。
  • 同步读取服务以 standby 后缀命名,延迟从库服务以 delayed 后缀命名,少量核心库可提供此服务。

实例命名规则(Instance)

  • 一套 PostgreSQL 集群由至少一个实例组成,每个实例都有集群内从零或一开始唯一分配的实例号。
  • 实例名由集群名 + 实例号通过连字符 - 拼接而成,例如: pg-test-1pg-test-2
  • 实例号一经分配不得修改,持续到实例下线销毁,不得重新分配使用。
  • 实例名将作为监控系统数据的 ins 标签,附加到该实例的所有数据上。
  • 如果是用主机/数据库 1:1 独占式部署,节点 Hostname 可以使用数据库实例名。

数据库命名规则(Database)

  • 数据库库名应当与集群、应用保持一致,必须为具有高区分度的英文单词。
  • 命名以 <tld>_<biz> 的形式构建,<tld> 为顶层业务线,也可用于区分不同环境,不用可以省略。
  • <biz>为具体业务名称,例如 pg-test-tt 集群可以使用库名 tt_testtest。这一点不强制,即允许创建不同于集群 <biz> 名称的其他数据库。
  • 对于分片库,<biz> 部分必须以shard结尾,但不应当包含分片号,例如 pg-testshard1pg-testshard2 都用 testshard 即可。
  • 多个部分使用-连接。例如:<biz>-chat-shard<biz>-payment等,总共不超过三段。

角色命名规范(Role/User)

  • 数据库超级用户 dbsu 有且仅有一个:postgres,用于流复制的用户命名为replicator
  • 用于监控的用户统一命名为 dbuser_monitor,用于日常管理的超级用户为:dbuser_dba
  • 程序/服务使用的业务用户默认使用 dbuser_<biz> 作为用户名,例如 dbuser_test。来自不同服务的访问应当使用独立的业务用户区分访问。
  • 个人用户申请的数据库用户同意使用 dbp_<name>,其中 name 为 LDAP 中的标准用户名。
  • 默认权限组命名固定为: dbrole_readonlydbrole_readwritedbrole_admindbrole_offline

模式命名规则(Schema)

  • 业务统一使用一个全局的 <prefix> 作为模式名,尽可能简短,默认设置为search_path 首位元素。
  • <prefix> 不得使用 publicmonitor ,不得与任何 PostgreSQL 扩展使用的模式名冲突,例如: timescaledbcitusrepackgraphqlnetcron,…… 不宜使用特殊名称:dbatrash
  • 分片模式命名规则采用:rel_<partition_total_num>_<partition_index>。中间为总分片数,目前固定使用 8192 ,后缀是分片号,从0开始计数。如 rel_8192_0,…… ,rel_8192_11,等等。
  • 创建额外的模式,或者使用 <prefix> 之外的模式名需要由研发解释其必要性。

关系命名规则(Relation)

  • 关系命名以表意清晰为第一要义,不要使用含混的缩写,也不应过分冗长,遵循通用命名规则。
  • 表名应当使用复数名词,并与历史惯例保持一致,应尽量避免带有不规则复数形式的单词。
  • 视图以v_作为命名前缀,物化视图使用mv_作为命名前缀,临时表以tmp_作为命名前缀。
  • 继承或分区表应当以父表表名作为前缀,并以子表特性(规则,分片范围等)作为后缀。
  • 时间范围分区使用起始区间作为命名后缀,首个分区如果无上界则由研发指定一个足够久远的时间点:年级分区:tbl_2023,月级分区 tbl_202304,天级分区 tbl_20230405,小时级分区 tbl_2023040518 ,默认分区以 _default 结尾。
  • 哈希分区命名以余数作为分区表名的后缀,列表分区由研发手工指定与列表项对应的合理分区表名。

索引命名规则(Index)

  • 创建索引时,应当显式指定索引名称,并与PostgreSQL默认命名规则保持一致。
  • 索引名称以表名作为前缀,主键索引以 _pkey 结尾,唯一索引以 _key 结尾,普通索引以 _idx 结尾,用于EXCLUDED约束的索引以_excl结尾。
  • 使用条件索引/函数索引时,应当在索引名称中体现使用的函数与条件内容。例如 tbl_md5_title_idxtbl_ts_ge_2023_idx,但不可超出长度限制。

字段命名规则(Attribute)

  • 禁止使用系统列保留字段名:oidxminxmaxcmincmaxctid
  • 主键列通常命名为id,或以id作为后缀。
  • 创建时间字段惯用名为created_time,最后修改时间惯用名为 updated_time
  • 布尔型字段建议使用is_has_ 等作为前缀。
  • 额外的灵活 JSONB 字段固定使用 extra 作为列名。
  • 其余各字段名需与已有表命名惯例保持一致,任何打破惯例的字段命名都应当做出书面设计说明与解释。

枚举项命名 (Enum)

  • 枚举项默认应当使用 camelCase,但也允许其他风格。

函数命名规则(Function)

  • 函数命名以动词起头: selectinsertdeleteupdateupsertcreate ,……。
  • 重要参数可以通过_by_ids_by_user_ids的后缀在函数名中体现。
  • 避免函数重载,同名函数尽量只保留一个。
  • 禁止通过 BIGINT/INTEGER/SMALLINT 等整型进行函数签名重载,调用时可能产生歧义。
  • 存储过程与函数中的变量使用命名参数,避免位置参数($1$2,…)。
  • 如果参数名与对象名出现冲突,在参数前添加 _,例如_user_id

注释规范(Comment)

  • 尽最大可能为各种对象提供注释(COMMENT),注释使用英文,言简意赅,一行为宜。
  • 对象的模式或内容语义发生变更时,请务必一并更新注释,并与实际情况保持同步。

0x02 设计规范

Suum cuique

建表注意事项

  • 建表 DDL 语句需要使用标准格式,SQL 关键词大写,其他小写。
  • 在字段名/表名/别名中统一使用小写,尽量不要区分大小写。如果遇到大小写混用的情况,或者与 SQL 关键词冲突的名称,需要使用双引号扩起进行引用。
  • 能使用专有类型的,不使用字符串。(数值,枚举,网络地址,货币,JSON,UUID等):使用正确的数据类型,能显著提高数据存储,查询,索引,计算的效率,并提高可维护性。
  • 优化列的布局,对齐类型可以有额外的性能/存储空间收益。
  • 唯一约束须由数据库保证,任何唯一列须有对应的唯一约束。EXCLUDE约束是泛化的唯一约束,可以在低频更新场景下用于保证数据完整性。

分区表注意事项

  • 如果单表超过百TB量级,或者每月增量数据超过十几GB量级,可以考虑进行表分区。
  • 分区的指导原则是,让每个分区的大小尽可能落在 1GB ~ 64GB 的舒适范围内。
  • 有条件按照时间范围分区的表优先按时间范围分区,通常使用的粒度包括: decade,year,month,day,hour,应当至少提前三个月创建好未来所需的分区。
  • 对于极端倾斜的数据分布,可以组合使用不同的时间粒度,例如: 1900 - 2000 一个大分区,2000 - 2020 按年分区,2020 后按月分区。使用时间分区时,表名使用分区下限界的值(无穷大则选用一个足够久远的值)。

宽表注意事项

  • 宽表(例如有几十个字段的表)可以考虑进行纵向拆分,通过相同的主键与主表相互引用。
  • 因为PostgreSQL MVCC机制,宽表的写放大现象更为明显,减少对宽表的频繁更新。
  • 互联网场景中,允许适当降低规范化等级,减少多表连接以提高性能。

主键注意事项

  • 每个表都必须身份列,原则上必须有主键,最低要求为拥有非空唯一约束

  • 身份列用于唯一标识表中的任一元组,逻辑复制与诸多三方工具有赖于此。

  • 主键如果包含多列,应当在建表DDL的字段列表之后,使用 PRIMARY KEY(a,b,...) 单列指定。

  • 主键原则上建议使用整型,可以谨慎使用 UUID 与长度受限的文本类型,使用其他类型需要显式说明与评估。

  • 主键通常使用单一整型列,原则上建议使用 BIGINT,谨慎使用 INTEGER,不允许使用 SMALLINT

  • 主键应使用 GENERATED ALWAYS AS IDENTITY 生成唯一主键;SERIALBIGSERIAL 仅当需要兼容 PG 10 以下版本时允许使用。

  • 主键可以使用 UUID 类型作为主键,建议用 UUID v1/v7;谨慎使用 UUIDv4 作为主键,随机 UUID 的局部性较差且有碰撞概率。

  • 使用字符串列作为主键时,应当添加长度限制。通常使用 VARCHAR(64),使用更长的字符串时应当进行说明与评估。

  • INSERT/UPDATE 时原则上禁止修改主键列的值,INSERT RETURNING 可用于返回自动生成的主键值。

外键注意事项

  • 定义外键时引用必须显式设置相应的动作:SET NULLSET DEFAULTCASCADE,慎用级联操作。
  • 外键引用的列,需要为其他表/本表上的主键列。
  • 互联网类业务,特别是分区表、水平分片库慎用外键,可以在应用层解决。

空值/默认值注意事项

  • 字段语义上没有零值与空值区分的,不允许空值存在,须为列配置NOT NULL约束。
  • 字段语义上带有默认值的,应当配置 DEFAULT 默认值。

数值类型注意事项

  • 常规数值字段使用INTEGER。容量拿不准的数值列使用BIGINT
  • 无特殊理由不要用SMALLINT,性能与存储提升甚小,但会有很多额外的问题。
  • 注意SQL标准不提供无符号整型,超过INTMAX但没超过UINTMAX的值需要升格存储。不要存储超过INT64MAX的值到BIGINT列中,会溢出为负数。
  • REAL 表示4字节浮点数,FLOAT 表示8字节浮点数。浮点数仅可用于末尾精度无所谓的场景,例如地理坐标。切记不要对浮点数使用等值判断,零值除外
  • 精确数值类型使用NUMERIC,如果可行,请用 NUMERIC(p)NUMERIC(p,s) 设置有效数字位数以及小数部分的有效位数。例如摄氏气温(37.0)可以用 NUMERIC(3,1) 类型来存储3位有效数字与1位小数。
  • 货币数值类型使用MONEY

文本类型注意事项

  • PostgreSQL的文本类型包括 char(n)varchar(n)text。默认情况下,可以使用 text 类型 ,不限制字符串长度,但受字段最大长度1GB限制。
  • 如果条件许可,优先使用 varchar(n) 类型来设置一个最大字符串长度,这会引入极微小的额外检查开销,但能规避一些脏数据与极端情况。
  • 避免使用char(n),该类型为了与SQL标准兼容,存在不合直觉的行为表现(补齐空格与截断),且并没有存储和性能优势。

时间类型注意事项

  • 时间只有两种存储方式:带时区的 TIMESTAMPTZ,不带时区的 TIMESTAMP
  • 建议使用带时区的 TIMESTAMPTZ,如果使用 TIMESTAMP 存储,必须使用0时区标准时。
  • 生成0时区时间请使用 now() AT TIME ZONE 'UTC' ,不能直接截断时区 now()::TIMESTAMP
  • 统一使用 ISO-8601 格式输入输出时间类型:2006-01-02 15:04:05,避免DMY与MDY问题。
  • 中国区域用户可以统一使用 Asia/Hong_Kong +8 时区,因为上海时区缩写 CST 有歧义。

枚举类型注意事项

  • 较稳定的,取值空间较小(几十到几百内)的字段应当使用枚举类型,不要使用整型与字符串表示。
  • 枚举内部使用动态整型实现,相比整型有可读性优势,相比字符串有性能、存储、可维护性上的优势。
  • 枚举项只能添加,无法删除,但是可以重命名现有枚举值。ALTER TYPE <enum_name> 用于修改枚举。

UUID类型注意事项

  • 请注意,全随机的 UUIDv4 用作主键时局部性太差,尽可能考虑用 UUIDv1 / v7 代替。
  • 一些 UUID 生成/处理函数需要额外的扩展插件,例如 uuid-ossppg_uuidv7 等,有此需求请在配置时指明。

JSON类型注意事项

  • 如无特殊原因,总是使用二进制存储的 JSONB 类型与相关函数,而非文本版本的 JSON
  • 请注意 JSON 中的原子类型与 PostgreSQL 对应类型的细微差别:与 JSON 字符串对应的text 类型中不允许出现 \u0000 零字符,与 JSON 数值类型对应的 numeric 中不允许出现 NaNinfinity。布尔值只接受小写的 truefalse 字面值。
  • 请注意JSON标准中的null对象和 SQL 标准中的空值 NULL 并非同一个概念。

数组类型注意事项

  • 当存储元素数量较少时,可以使用数组字段代替单独。
  • 适合用于存储元素数量相对较少且变化不频繁的数据。如果数组中的元素数量非常大或经常变化,考虑使用单独的表来存储数据,并使用外键关联。
  • 高维度的浮点数组,可以考虑使用 pgvector 扩展提供的专用数据类型。

GIS类型注意事项

  • GIS 类型默认使用 srid=4326 参考坐标系。
  • 经纬度坐标点应当使用 Geography 类型,无需显式指定参考系坐标 4326

触发器注意事项

  • 触发器会提高数据库系统的复杂度与维护成本,原则上不鼓励使用。禁止使用规则系统,此类需求应当使用触发器替代。

  • 触发器的典型场景是,在修改某一行后自动修改 updated_time 为当前时间戳,或者将表的增删改动作记录到另一张日志表中,或者维持两张表在业务上的一致性。

  • 触发器中的操作是事务性的,意味着如果触发器或触发器中的操作失败,整个事务都会回滚,所以请充分测试并证明触发器的正确性。对于递归调用、执行复杂查询死锁,多个触发器执行顺序等情况需要特别关注。

存储过程/函数注意事项

  • 函数/存储过程适用于封装事务,减少并发冲突,减少网络往返,减少返回数据量,执行少量自定义逻辑。

  • 存储过程不适合进行复杂计算,不适合进行平凡/频繁的类型转换与包装。在关键高负载系统中,应当移除数据库中不必要的计算密集型逻辑,例如在数据库中使用SQL进行WGS84到其他坐标系的换算。与数据获取、筛选密切关联的计算逻辑可以使用函数/存储过程:例如PostGIS中的几何关系判断。

  • 不再使用的,被替换的函数与存储过程应当及时下线,避免与未来的函数发生冲突。

  • 使用统一的函数创建语法格式,签名单独占用一行(函数名与参数),返回值单启一行,语言为第一个标签。一定要标注函数易变性等级:IMMUTABLE, STABLE, VOLATILE。添加属性标签,如:RETURNS NULL ON NULL INPUTPARALLEL SAFEROWS 1 等。

    CREATE OR REPLACE FUNCTION
      nspname.myfunc(arg1_ TEXT, arg2_ INTEGER)
      RETURNS VOID
    LANGUAGE SQL
    STABLE
    PARALLEL SAFE
    ROWS 1
    RETURNS NULL ON NULL INPUT
    AS $function$
    SELECT 1;
    $function$;
    

使用合理的Locale选项

使用合理的字符编码与本地化配置

  • 必须使用 UTF8 字符编码,严格禁止使用其他任何字符编码。
  • 必须使用 C 作为 LC_COLLATE 默认排序规则,有特殊需求必须在DDL/查询子句中显式指定来实现。
  • 字符集 LC_CTYPE 默认使用 en_US.UTF8,一些扩展依赖字符集信息方可正常工作,如 pg_trgm

索引相关注意事项

  • 所有在线查询必须针对其访问模式设计相应索引,除极小表外不允许全表扫描。
  • 索引有代价,不允许创建不使用的索引,应当及时清理不再使用的索引。
  • 建立联合索引时,应当将区分度,选择率高的列放在前面,例如 ID,时间戳等。
  • GiST索引可用于解决近邻查询问题,传统B树索引无法提供对KNN问题的良好支持。
  • 对于值与堆表的存储顺序线性相关的数据,如果通常的查询为范围查询,建议使用BRIN索引。最典型场景如仅追加写入的时序数据,BRIN索引相比Btree更为高效。
  • 针对 JSONB / 数组字段进行检索时,可以使用 GIN 索引加速查询。

明确B树索引空值的顺序

  • 如在可空列上有排序需求,需要在查询与索引中明确指定NULLS FIRST还是NULLS LAST
  • 注意,DESC排序的默认规则是NULLS FIRST,即空值会出现在排序的最前面,通常这不是期望行为。
  • 索引的排序条件必须与查询匹配,如:CREATE INDEX ON tbl (id DESC NULLS LAST);

禁止在大字段上建立索引

  • 被索引字段大小无法超过2KB(1/3的页容量),在文本类型上创建索引需要谨慎,被索引的文本应当使用带有长度约束的 varchar(n) 类型。
  • 文本类型用作主键时,必须设置最大长度。原则上长度不应当超过 64 个字符,特殊情况需显式说明评估。
  • 如有大字段索引需求,可以考虑对大字段取哈希,并建立函数索引。或使用其他类型的索引(GIN)。

充分利用函数索引

  • 任何可以由同一行其他字段推断得出的冗余字段,可以使用函数索引替代。
  • 对于经常使用表达式作为查询条件的语句,可以使用表达式或函数索引加速查询。
  • 典型场景:建立大字段上的哈希函数索引,为需要左模糊查询的文本列建立 reverse 函数索引。

充分利用部分索引

  • 查询中查询条件固定的部分,可以使用部分索引,减小索引大小并提升查询效率。
  • 查询中某待索引字段若只有有限几种取值,也可以建立几个相应的部分索引。
  • 如果部分索引中的列会被频繁更新,请关注这些索引的膨胀情况

0x03 查询规范

The limits of my language mean the limits of my world.

—Ludwig Wittgenstein

使用服务接入

  • 生产数据库接入必须通过域名接入服务,严禁使用 IP 地址直连。
  • 服务与接入使用 VIP,LVS/HAProxy 屏蔽集群实例成员的角色变化,主从切换无需应用重启。

读写分离

  • 互联网业务场景:写请求必须走主库,通过 Primary 服务访问。
  • 读请求原则上走从库,通过 Replica 服务访问。
  • 例外情况:需要读己之写的一致性保证,且检测到显著的复制延迟时,只读请求可以访问主库;或向DBA申请提供 Standby 服务。

快慢分离

  • 生产中1毫秒以内的查询称为快查询,生产中超过1秒的查询称为慢查询。
  • 慢查询必须走离线从库 —— Offline 服务/实例,应当在执行时设置超时。
  • 生产中的在线普通查询执行时长原则上应当控制在 1ms 内。
  • 生产中的在线普通查询执行时长,超过10ms需修改技术方案,优化达标后再上线。
  • 在线查询应当配置10ms 数量级或更快的 Timeout,避免堆积造成雪崩。
  • 禁止从 Primary 上 ETL 数据,应当使用 Offline 服务从专用实例取数。

使用连接池

  • 生产应用必须通过连接池访问数据库,通过 1:1 部署的 Pgbouncer 代理访问 PostgreSQL 数据库。Offline 服务,个人用户严禁直接使用连接池。
  • Pgbouncer 连接池默认使用 Transaction Pooling 模式,一些会话级别的功能可能无法使用(比如Notify/Listen),需要特别注意。在此模式下,1.21 以前的 Pgbouncer 不支持使用 Prepared Statements。特殊场景可以使用 Session Pooling 或绕开连接池直接访问数据库,需要 DBA 审核特批。
  • 使用连接池时禁止修改连接状态,包括修改连接参数,修改搜索路径,更换角色,更换数据库。万不得已修改后必须彻底销毁连接,将状态变更后的连接放回连接池会导致污染扩散。严禁使用 pg_dump 通过 Pgbouncer 转储数据。

为查询语句配置主动超时

  • 应用应当为所有的语句配置主动超时,超时后主动取消请求,避免雪崩。(Go context)
  • 周期性执行的语句,必须配置小于执行周期的超时 Timeout,避免雪崩。
  • HAProxy 配置有 24 小时连接默认超时,用于滚动过期长连接。请不要在离线实例上运行执行时间超过1天的 SQL,有此需求由DBA特批调整。

关注复制延迟

  • 应用必须意识到主从之间的同步延迟,并妥善处理好复制延迟超出合理范围的情况。
  • 常规情况下,复制延迟在 100µs / 几十KB 的数量级,但是在极端情况下,从库可能会出现分钟/小时级的复制延迟,应用应当知晓这种现象,并有相应的降级方案 —— 选择从主库读取,稍后重试,或直接报错。

重试失败的事务

  • 查询可能因为并发争用,管理员命令等原因被杀死,应用需要意识到这一点,并在必要时重试。
  • 应用在数据库大量报错时可以触发断路器熔断,避免雪崩。但要注意区分错误的类型与性质。

掉线重连

  • 数据库连接可能因为各种原因被中止,应用必须有掉线重连机制。
  • 可以使用SELECT 1作为心跳包查询,检测连接的有消息,并定期保活。

在线服务应用代码禁止执行DDL

  • 生产应用严禁执行 DDL,不要在应用代码里搞个大新闻。
  • 例外场景:为分区表创建新的时间分区,可由应用谨慎管理。
  • 特殊例外:办公系统使用的数据库,例如 Gitlab / Jira/ Confluence 等可以授予应用 DDL 权限。

SELECT语句显式指定列名

  • 避免使用SELECT *,或在RETURNING子句中使用*。请使用具体的字段列表,不要返回用不到的字段。当表结构发生变动时(例如,新值列),使用列通配符的查询很可能会发生列数不匹配的错误。
  • 一些表的字段经过维护之后,顺序会发生变化,例如:将 INTEGER 主键 id 升级为 BIGINT 后,id 的列顺序会到最后一列。此问题只能在维护迁移时择机修复,研发应当克制调整列顺序的强迫症,并在 SELECT 语句中显式指定列的顺序
  • 例外:当存储过程返回具体的表行类型时,允许使用通配符。

禁止在线查询全表扫描

  • 例外情况:常量极小表,极低频操作,表/返回结果集很小(百条记录/百KB内)。
  • 在首层过滤条件上使用诸如!=, <>的否定式操作符会导致全表扫描,必须避免。

禁止在事务中长时间等待

  • 开启事务后必须尽快提交或回滚,超过10分钟的IDEL IN Transaction将被强制杀死。
  • 应用应当开启 AutoCommit,避免BEGIN之后没有配对的ROLLBACKCOMMIT
  • 尽量使用标准库提供的事务基础设施,不到万不得已不要手动控制事务。

使用 count 计数时的注意事项

  • count(*)统计行数的标准语法,与空值无关。
  • count(col)统计的是col列中的非空记录数。该列中的NULL值不会被计入。
  • count(distinct col)col列除重计数,同样忽视空值,即只统计非空不同值的个数。
  • count((col1, col2))对多列计数,即使待计数的列全为空也会被计数,(NULL,NULL)有效。
  • a(distinct (col1, col2))对多列除重计数,即使待计数列全为空也会被计数,(NULL,NULL)有效。

使用聚合函数的注意事项

  • 除了count之外的所有聚合函数都会忽略空值输入,因此当输入值全部为空时,结果是NULL。但count(col)在这种情况下会返回 0,是一个例外。
  • 如果聚集函数返回空并不是期望的结果,使用 coalesce 来设置缺省值。

谨慎处理空值

  • 明确区分零值与空值,空值使用IS NULL进行等值判断,零值使用常规的=运算符进行等值判断。
  • 空值作为函数输入参数时应当带有类型修饰符,否则对于有重载的函数将无法识别使用何者。
  • 注意空值比较逻辑:任何涉及到空值比较运算结果都是unknown,需要注意unknown参与布尔运算的逻辑:
    • andTRUE or UNKNOWN会因为逻辑短路返回TRUE
    • orFALSE and UNKNOWN会因为逻辑短路返回FALSE
    • 其他情况只要运算对象出现UNKNOWN,结果都是UNKNOWN
  • 空值与任何值的逻辑判断,其结果都为空值,例如NULL=NULL返回结果是NULL而不是TRUE/FALSE
  • 涉及空值与非空值的等值比较,请使用``IS DISTINCT FROM 进行比较,保证比较结果非空。
  • 空值与聚合函数:聚合函数当输入值全部为NULL时,返回结果为NULL。

注意序列号空缺

  • 当使用Serial类型时,INSERTUPSERT等操作都会消耗序列号,该消耗不会随事务失败而回滚。
  • 当使用整型 INTEGER 作为主键,且表存在频繁插入冲突时,需要关注整型溢出的问题。

使用游标后必须及时关闭

重复查询使用准备语句

  • 重复的查询应当使用准备语句(Prepared Statement),消除数据库硬解析的CPU开销。低于 1.21 版本的 Pgbouncer 无法在事务池化模式中支持此功能,请特别注意。
  • 准备语句会修改连接状态,请注意连接池对于准备语句的影响。

选择合适的事务隔离等级

  • 默认隔离等级为读已提交,适合大多数简单读写事务,普通事务选择满足需求的最低隔离等级。
  • 需要事务级一致性快照的写事务,请使用可重复读隔离等级。
  • 对正确性有严格要求(例如与钱有关)的写入事务,使用可序列化隔离等级。
  • 在RR与SR隔离等级出现并发冲突时,应用应当视错误类型进行积极的重试。

r h 09判断结果存在性不要使用count

  • 使用SELECT 1 FROM tbl WHERE xxx LIMIT 1判断是否存满足条件的列,要比Count快。
  • 可以使用SELECT exists(SELECT * FROM tbl WHERE xxx LIMIT 1)将存在性结果转换为布尔值。

使用RETURNING子句一次性取回修改后的结果

  • RETURNING 子句可以在 INSERTUPDATEDELETE 语句后使用,有效减少数据库交互次数。

使用UPSERT简化逻辑

  • 当业务出现插入-失败-更新的操作序列时,考虑使用UPSERT替代。

利用咨询锁应对热点并发

  • 针对单行记录的极高频并发写入(秒杀),应当使用咨询锁对记录ID进行锁定。
  • 如果能在应用层次解决高并发争用,就不要放在数据库层面进行。

优化IN操作符

  • 使用 EXISTS 子句代替IN操作符,性能更佳。
  • 使用 =ANY(ARRAY[1,2,3,4]) 代替 IN (1,2,3,4),效果更佳。
  • 控制参数列表的大小,原则上不要超过1万个,超过时可以考虑分批处理。

不建议使用左模糊搜索

  • 左模糊搜索WHERE col LIKE '%xxx'无法充分利用B树索引,如有需要,可用reverse表达式函数索引。

使用数组代替临时表

  • 考虑使用数组替代临时表,例如在获取一系列ID的对应记录时。=ANY(ARRAY[1,2,3]) 要比临时表JOIN好。

0x04 管理规范

使用 Pigsty 搭建 PostgreSQL 集群与基础设施

  • 生产环境统一使用 Pigsty 主干版本,在 x86_64 机器, CentOS 7.9 / RockyLinux 8.8 操作系统上部署数据库。
  • pigsty.yml 配置文件通常包含了高度敏感的重要机密信息,应当使用 git 进行版本化管理,并严格控制访问权限。
  • files/pki 内生成的 CA 私钥与其他证书应当妥善保管,定期将备份至安全区域存储归档,并严格控制访问权限。
  • 所有密码都不允许使用默认值,确保都已经修改为强度足够的新密码。
  • 严格控制管理节点与配置代码仓库的的访问权限,仅限 DBA 登陆与访问。

监控系统是必选项

  • 任何部署必须有一套监控系统,生产环境至少使用两套 Infra 节点以提供冗余。

根据需求合理规划集群架构

  • 任何由DBA管理的生产数据库集群,必须带有至少一个在线从库,用于在线故障切换。
  • 默认使用 oltp 模板,分析类数据库使用 olap 模板,财务库使用 crit 模板,小微虚拟机(四核内)使用 tiny 模板。
  • 年增数据量超过1TB的业务,或者写入 TPS 超过3~5万的集群,可以考虑搭建水平分片集群。

使用 Patroni 与 Etcd 配置集群高可用

  • 生产数据库集群使用 Patroni 作为高可用组件,使用 etcd 作为 DCS。
  • etcd 使用专用虚拟机集群,3 ~ 5 个节点,严格打散分布在不同机柜上。
  • 必须开启 Patroni Failsafe 模式,确保 etcd 故障时集群主库可以继续工作。

使用 pgBackRest 与 MinIO 配置集群PITR

  • 生产数据库集群使用 pgBackRest 作为备份恢复/PITR方案,使用 MinIO 作为备份存储仓库。
  • MinIO 使用多节点多盘集群,亦可使用 S3 / OSS / COS 服务代替,冷备份必须设置密码加密。
  • 所有数据库集群每天进行一次本地全量备份,保留最近一周的备份与WAL,每隔一月存留一个全备。
  • 出现 WAL 归档错误时,应当及时检查备份仓库并排查问题。

核心业务数据库配置注意事项

  • 核心业务集群至少需要配置两个在线从库,其中一个为专用离线查询实例。
  • 核心业务集群需要搭建一套延迟24小时的延迟从库集群,用于应急数据恢复。
  • 核心业务集群通常采用异步提交,与钱有关则采用同步提交。

财务数据库配置注意事项

  • 财务数据库集群需要至少两个在线从库,其中一个为专用同步 Standby 实例,并启用 Standby 服务接入。
  • 与钱有关的库必须使用 RPO = 0 的 crit 模板,启用同步提交确保数据零丢失,视情况启用 Watchdog。
  • 与钱有关的库必须强制打开数据校验和,视情况打开全量 DML 日志。

使用合理的字符编码与本地化配置

  • 必须使用 UTF8 字符编码,严格禁止使用其他任何字符编码。
  • 必须使用 C 作为 LC_COLLATE 默认排序规则,有特殊需求必须在DDL/查询子句中显式指定来实现。
  • 字符集 LC_CTYPE 默认使用 en_US.UTF8,一些扩展依赖字符集信息方可正常工作,如 pg_trgm

业务数据库管理注意事项

  • 同一个集群内允许创建多个不同的数据库,必须使用 Ansible 剧本新建业务数据库。
  • 所有业务数据库都必须同步存在于 Pgbouncer 连接池中。

业务用户管理注意事项

  • 不同的业务/服务必须使用不同的数据库用户,必须使用 Ansible 剧本新建业务用户。
  • 所有生产业务用户都必须同步存在于 Pgbouncer 连接池的用户列表文件中。
  • 个人用户应当设置默认有效期为 90 天的密码并定时更换。
  • 个人用户只允许从跳板机访问有权限的集群 Offline 实例,或带有 pg_offline_query 的从库。

扩展插件管理注意事项

  • 安装新扩展时,必须先在集群所有实例中使用 yum/apt 安装对应大版本的扩展插件二进制软件包。
  • 启用扩展前,需要确认扩展是否需要加入 shared_preload_libraries ,如果需要应当安排滚动重启。
  • 注意 shared_preload_libraries 优先级顺序, citustimescaledbpgml 通常要放在最前面。
  • pg_stat_statementsauto_explain 是必选插件,必须在所有集群中启用。
  • 安装扩展统一使用 dbsu 进行,在业务数据库中 CREATE EXTENSION 执行创建。

数据库XID与年龄注意事项

  • 关注数据库与表的年龄,避免XID事务号用尽。使用超过 20% 应当关注,超过 50% 应当立即介入处理。
  • 处理 XID 时,按年龄从大到小顺序挨个对表执行 VACUUM FREEZE

数据库表与索引膨胀注意事项

  • 关注表与索引的膨胀率,避免索引性能劣化,使用 pg_repack 在线处理表/索引膨胀问题。
  • 一般情况下,膨胀率超过 50% 的索引与表可以考虑进行重整处理。
  • 处理超过 100GB 的表膨胀时,应当特别注意,并挑选业务低谷时进行。

数据库重启注意事项

  • 重启数据库前,执行 CHECKPOINT 两次,强制脏页刷盘,可加速重启过程。
  • 重启数据库前,执行 pg_ctl reload 重载配置确认配置文件正常可用。
  • 重启数据库可使用 pg_ctl restart 或 patronictl 同时重启整个集群。
  • 严禁使用 kill -9 关闭任何数据库进程。

复制延迟注意事项

  • 监控复制延迟,使用复制槽时更必须十分留意。

新从库数据预热

  • 高负载业务集群添加新从库实例时,应当对新数据库实例进行预热,逐步调整并应用 HAProxy 实例权重,分梯度上量:4,8,16,32,64,100。可以使用 pg_prewarm 将热数据加载至内存。

数据库发布流程

  • 线上数据库发布需要经过研发自测,主管审核,QA审核(可选),DBA审核几个评估阶段。
  • 研发自测阶段,应当由研发确保变更在开发、预发环境执行正确无误。
    • 如果是新建表,应当给出记录数量级,数据日增量预估值,读写吞吐量级预估。
    • 如果是新建函数,应当给出平均执行时间与极端情况说明。
    • 如果是模式变更,必须梳理清楚所有上下游依赖。
    • 如果是数据变更,记录订正,必须给出回滚 SQL。
  • 研发 Team Leader 需要对变更进行评估与审核,对变更内容负责。
  • DBA对发布的形式与影响进行评估与审核,提出审核意见,打回或统一执行

数据工单格式

  • 数据库变更通过平台进行,每个变更一个工单。
  • 标题清晰:某某业务需在 xx 库执行 yy 动作。
  • 目标明确:每个步骤需要在哪些实例上执行哪些操作,结果如何校验。
  • 回滚方案:任何变更都需要提供回滚方案,新建也需要提供清理脚本。
  • 任何变更都需要记录归档,有完善的审批记录,首先由研发上级TL Review 审批通过后由 DBA 审批。

数据库变更发布注意事项

  • 使用统一的发布窗口,每天 16:00 统一收集当日变更依次执行;16:00点后TL确认的需求将顺延至第二天执行。19:00 后不允许数据库发布,紧急发布请TL做特殊说明,抄送CTO审批同意后执行。

  • 数据库 DDL 变更 DML 变更统一使用管理员用户 dbuser_dba 远程执行,确保默认权限正常工作。

  • 业务管理员在自行执行 DDL 时,必须SET ROLE dbrole_admin 后再执行发布,确保默认权限。

  • 任何变更都需要有回滚预案方可执行,极个别无法回滚的操作需要特别谨慎处理(例如枚举加值)

  • 数据库变更使用 psql 命令行工具,连接到集群主库执行,使用 \i 执行脚本或 \e 手工分批执行。

删除表注意事项

  • 生产数据表 DROP 应当首先重命名,冷却 1~3 天确认没有访问后再移除。
  • 清理表时必须梳理所有依赖,包括直接间接依赖的对象:触发器,外键引用等。
  • 待删除的临时表通常放置于 trash Schema 中,通过 ALTER TABLE SET SCHEMA 修改模式名。
  • 高负载业务集群中,移除特别大的表 (> 100G) 时挑选业务低谷进行,避免抢占 I/O 。

创建与删除索引注意事项

  • 必须使用 CREATE INDEX CONCURRENTLY 并发创建索引,使用 DROP INDEX CONCURRENTLY 并发移除索引。
  • 重建索引时,总是先创建新索引,再移除旧索引,并修改新索引名与旧索引保持一致。
  • 创建索引失败后,应当及时移除 INVALID 的索引,修改索引后,使用 analyze 重新收集表上的统计数据。
  • 业务空闲时,可以启用并行索引创建,并设置 maintenance_work_mem 为更大的值加速索引创建。

审慎地进行模式变更

  • 尽可能避免整表重写式的变更,1GB 以内的表允许全表重写,DBA 应当在变更时告知所有相关业务方。
  • 向现有表中添加新列时,应当避免在默认值中使用 VOLATILE 的函数,避免全表重写。
  • 变更列类型时,必要时应当重建所有依赖该类型的函数,视图,并 ANALYZE 刷新统计信息。

控制数据写入的批次规模

  • 大批量写入操作应当切分为小批量进行,避免一次产生大量WAL或占用 I/O。
  • 大批量 UPDATE 后,执行 VACUUM 回收死元组占用的空间。
  • 执行 DDL 语句本质是对系统目录的修改,同样需要控制一个批次内的DDL语句数量。

数据加载注意事项

  • 使用COPY加载数据,如有需要可以并行执行。
  • 加载数据前可以临时关闭autovacuum,按需禁用触发器,并在加载完后再建立约束与索引。
  • 调大 maintenance_work_mem,增大max_wal_size
  • 加载完成后执行vacuum verbose analyze table

数据库迁移、大版本升级注意事项

  • 生产环境统一使用标准迁移搭建剧本逻辑,通过蓝绿部署实现不停机集群迁移、大版本升级等需求。
  • 对于停机时间没有要求的集群,可以使用 pg_dump | psql 逻辑导出导入的方式停机升级。

数据误删/误更新处理流程

  • 事故发生后,立即评估是否需要停机止血,评估影响规模,决定处理手段。
  • 研发侧如有办法恢复,优先由研发自行通过 SQL 发布进行订正;否则使用 pageinspectpg_dirtyread 从坏表中抢救数据。
  • 若有延迟从库,从延时从库中抽取数据进行修复。首先确认误删时间点,推进延迟从库至该 XID 后抽取数据。
  • 大面积误删误写,经与业务沟通同意后,执行原地 PITR 回滚至特定时间。

数据腐坏处理流程

  • 确认从库数据是否可用于恢复,若从库数据无恙可先 Switchover 至从库。
  • 临时关闭 auto_vacuum ,定位错误根因,替换故障磁盘并补充新从库。
  • 若系统目录损坏,或使用 pg_filedump 从表二进制文件中恢复数据。
  • 若 CLOG 损坏,使用 dd 生成仿造提交记录。

数据库连接打满注意事项

  • 出现连接打满现象(雪崩)时,立即使用杀连接查询治标止损:pg_cancel_backendpg_terminate_backend
  • 使用 pg_terminate_backend 中止所有普通后端进程,从每秒一次(psql \watch 1)开始。并从监控系统确认连接情况,如果继续堆积,则不断提高杀连接查询的执行频次,例如每 0.1 秒一次,直到不再堆积为止。
  • 从监控系统确认止血后,尝试停止杀连接,若重新出现堆积则立即恢复杀连接。立即分析根因并进行相应处理(升配,限流,加索引等)

FerretDB:假扮成MongoDB的PG

微信公众号原文链接

MongoDB 曾经是一项令人惊叹的技术,让开发者能够抛开关系型数据库的“模式束缚”,快速构建应用程序。然而随着时间推移,MongoDB 放弃了它的开源本质,这使得许多开源项目和早期商业项目无法使用它。

大多数 MongoDB 用户其实并不需要 MongoDB 提供的高级功能,但他们确实需要一个易于使用的开源文档数据库解决方案。PostgreSQL 的 JSON 功能支持已经足够完善了:二进制存储 JSONB,GIN 任意字段索引 ,各种 JSON 处理函数,JSON PATH 和 JSON Schema,PG早已是一个功能完备,性能强大的文档数据库了。但是提供替代的功能,和直接仿真还是不一样的。

为了填补这个空白,FerretDB 应运而生,旨在提供一个真正开源MongoDB 替代。这是一个非常有趣的项目,之前的名字叫 “MangoDB”,因为有碰瓷 “MongoDB” 的嫌疑(芒果DB vs 蒙古DB),所以在 1.0 版本改成了现在的名字 FerretDB。FerretDB 可以为使用 MongoDB 驱动的应用提供一个丝滑迁移到 PostgreSQL 的过渡方案。

它的功能就是让 PostgreSQL 假扮成 MongoDB。它是一个为 PG 提供 MongoDB Wire Protocol 支持的协议转换中间件/Proxy。上次做过这种事的插件是 AWS 的 Babelfish,让 PostgreSQL 兼容 SQL Service 的线缆协议假扮成 Microsoft SQL Server。

FerretDB 作为一个选装组件,对丰富 PostgreSQL 生态大有裨益。Pigsty 在 1.x 中就提供了基于 Docker 的 FerretDB 模板,在 v2.3 中更是提供了原生部署支持。目前,Pigsty 社区已经与 FerretDB 社区成为了合作伙伴,后续将进行深度的合作与适配支持。

本文简单介绍了 FerretDB 的安装、部署与使用。


配置

在部署 Mongo (FerretDB) 集群前,你需要先在配置清单中使用相关参数定义好它。下面的例子将默认的单节点 pg-meta 集群的 meta 数据库作为 FerretDB 的底层存储:

ferret:
  hosts: { 10.10.10.10: { mongo_seq: 1 } }
  vars:
    mongo_cluster: ferret
    mongo_pgurl: 'postgres://dbuser_meta:DBUser.Meta@10.10.10.10:5432/meta'

这里 mongo_clustermongo_seq 属于不可或缺的身份参数,对于 FerretDB 来说,还有一个必须提供的参数是 mongo_pgurl,指定了底层 PG 的位置。

您可以使用 服务 来接入高可用的 PostgreSQL 集群,并部署多个 FerretDB 实例副本并绑定 L2 VIP 以实现 FerretDB 层本身的高可用。

ferret-ha:
  hosts:
    10.10.10.45: { mongo_seq: 1 }
    10.10.10.46: { mongo_seq: 2 }
    10.10.10.47: { mongo_seq: 3 }
  vars:
    mongo_cluster: ferret
    mongo_pgurl: 'postgres://test:test@10.10.10.3:5436/test'
    vip_enabled: true
    vip_vrid: 128
    vip_address: 10.10.10.99
    vip_interface: eth1

管理

创建Mongo集群

在配置清单中定义好MONGO集群后,您可以使用以下命令完成安装。

./mongo.yml -l ferret   # 在 ferret 分组上安装“MongoDB/FerretDB”

因为 FerretDB 使用了 PostgreSQL 作为底层存储,所以重复运行此剧本通常并无大碍。

移除Mongo集群

要移除 Mongo/FerretDB 集群,运行 mongo.yml剧本的子任务:mongo_purge,并使用 mongo_purge 命令行参数即可:

./mongo.yml -e mongo_purge=true -t mongo_purge

安装MongoSH

您可以使用 MongoSH 作为客户端工具访问 FerretDB 集群

cat > /etc/yum.repos.d/mongo.repo <<EOF
[mongodb-org-6.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/6.0/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-6.0.asc
EOF
yum install -y mongodb-mongosh

当然,您也可以直接安装 mongosh 的 RPM 包:

rpm -ivh https://mirrors.tuna.tsinghua.edu.cn/mongodb/yum/el7/RPMS/mongodb-mongosh-1.9.1.x86_64.rpm

连接到FerretDB

你可以使用 MongoDB 连接串,用任何语言的 MongoDB 驱动访问 FerretDB,这里以上面安装的 mongosh 命令行工具为例:

mongosh 'mongodb://dbuser_meta:DBUser.Meta@10.10.10.10:27017?authMechanism=PLAIN'mongosh 'mongodb://test:test@10.10.10.11:27017/test?authMechanism=PLAIN'

Pigsty 管理的 PostgreSQL 集群默认使用 scram-sha-256 作为默认的认证方式,因此,您必须使用 PLAIN 认证方式连接至 FerretDB。参阅 FerretDB:认证[17] 获取详细信息。

你也可以使用其他 PostgreSQL 用户来访问 FerretDB,只要在连接串中指定即可:

mongosh 'mongodb://dbuser_dba:DBUser.DBA@10.10.10.10:27017?authMechanism=PLAIN'

快速上手

你可以连接到 FerretDB 并假装它是一个 MongoDB 集群。

$ mongosh 'mongodb://dbuser_meta:DBUser.Meta@10.10.10.10:27017?authMechanism=PLAIN'

MongoDB 的命令会被翻译为SQL命令,在底下的 PostgreSQL 中执行:

use test                            # CREATE SCHEMA test;
db.dropDatabase()                   # DROP SCHEMA test;
db.createCollection('posts')        # CREATE TABLE posts(_data JSONB,...)
db.posts.insert({                   # INSERT INTO posts VALUES(...);
    title: 'Post One',body: 'Body of post one',category: 'News',tags: ['news', 'events'],
    user: {name: 'John Doe',status: 'author'},date: Date()}
)
db.posts.find().limit(2).pretty()   # SELECT * FROM posts LIMIT 2;
db.posts.createIndex({ title: 1 })  # CREATE INDEX ON posts(_data->>'title');

如果你不是很熟悉 MongoDB,这里有一个快速上手教程,同样适用于 FerretDB: Perform CRUD Operations with MongoDB Shell[18]

如果你希望生成一些样例负载,可以使用 mongosh 执行以下的简易测试剧本:

cat > benchmark.js <<'EOF'
const coll = "testColl";
const numDocs = 10000;

for (let i = 0; i < numDocs; i++) {  // insert
  db.getCollection(coll).insert({ num: i, name: "MongoDB Benchmark Test" });
}

for (let i = 0; i < numDocs; i++) {  // select
  db.getCollection(coll).find({ num: i });
}

for (let i = 0; i < numDocs; i++) {  // update
  db.getCollection(coll).update({ num: i }, { $set: { name: "Updated" } });
}

for (let i = 0; i < numDocs; i++) {  // delete
  db.getCollection(coll).deleteOne({ num: i });
}
EOF

mongosh 'mongodb://dbuser_meta:DBUser.Meta@10.10.10.10:27017?authMechanism=PLAIN' benchmark.js

你可以查阅 FerretDB 支持的 MongoDB命令,同时还有一些已知的区别,对于基本的使用来说,通常不是什么大问题。

  1. FerretDB uses the same protocol error names and codes, but the exact error messages may be different in some cases.
  2. FerretDB does not support NUL (\0) characters in strings.
  3. FerretDB does not support nested arrays.
  4. FerretDB converts -0 (negative zero) to 0 (positive zero).
  5. Document restrictions:
    • document keys must not contain . sign;
    • document keys must not start with $ sign;
    • document fields of double type must not contain Infinity, -Infinity, or NaN values.
  6. When insert command is called, insert documents must not have duplicate keys.
  7. Update command restrictions:
    • update operations producing Infinity, -Infinity, or NaN are not supported.
  8. Database and collection names restrictions:
    • name cannot start with the reserved prefix _ferretdb_;
    • database name must not include non-latin letters;
    • collection name must be valid UTF-8 characters;
  9. FerretDB offers the same validation rules for the scale parameter in both the collStats and dbStats commands. If an invalid scale value is provided in the dbStats command, the same error codes will be triggered as with the collStats command.

剧本

Pigsty 提供了一个内置的剧本: mongo.yml,用于在节点上安装 FerretDB 集群。

mongo.yml

该剧本由以下子任务组成:

  • mongo_check :检查 mongo 身份参数•mongo_dbsu :创建操作系统用户 mongod•mongo_install :安装 mongo/ferretdb RPM包•mongo_purge :清理现有 mongo/ferretdb 集群(默认不执行)•mongo_config :配置 mongo/ferretdb
  • mongo_cert :签发 mongo/ferretdb SSL证书
  • mongo_launch :启动 mongo/ferretdb 服务•mongo_register:将 mongo/ferretdb 注册到 Prometheus 监控中

监控

MONGO 模块提供了一个简单的监控面板:Mongo Overview

Mongo Overview

Mongo Overview: Mongo/FerretDB 集群概览

这个监控面板提供了关于 FerretDB 的基本监控指标,因为 FerretDB 底层使用了 PostgreSQL,所以更多的监控指标,还请参考 PostgreSQL 本身的监控。


参数

MONGO[24] 模块中提供了9个相关的配置参数,如下表所示:

参数 类型 级别 注释
mongo_seq int I mongo 实例号,必选身份参数
mongo_cluster string C mongo 集群名,必选身份参数
mongo_pgurl pgurl C/I mongo/ferretdb 底层使用的 PGURL 连接串,必选
mongo_ssl_enabled bool C mongo/ferretdb 是否启用SSL?默认为 false
mongo_listen ip C mongo 监听地址,默认留控则监听所有地址
mongo_port port C mongo 服务端口,默认使用 27017
mongo_ssl_port port C mongo TLS 监听端口,默认使用 27018
mongo_exporter_port port C mongo exporter 端口,默认使用 9216
mongo_extra_vars string C MONGO 服务器额外环境变量,默认为空白字符串

向量是新的 JSON

微信公众号原文 | 英文原文

向量是新的JSON”,这本身就是一种很有趣的说法。因为向量(Vector)是一种已经被深入研究过的数学结构,而 JSON 是一种数据交换格式。然而,在数据存储和检索的世界中,这两种数据表示方式都已经成为了各自领域的通用语言,成为(或即将成为)现代应用开发中必不可少的要素。如果按当下的趋势发展,向量将会像 JSON 一样,成为构建应用时的关键要素

生成型AI 引发的热潮促使开发者寻找一种简便的方法来存储与查询这些系统的输出。出于很多因素,PostgreSQL 成为了最自然的选择。但即使是生成型AI 炒翻天也无法改变这一事实:向量并不是一种新的数据模式,它作为一种数学概念已经存在数百年了,而机器学习领域也对其已有半个世纪多的研究。向量的基础数据结构 —— 数组,几乎在所有初级导论性质的计算机科学课程中都会讲授。连 PostgreSQL 对向量运算的支持也已经有20多年的历史了!

高中数学知识:向量的余弦距离与相似度

那有什么东西是新的呢?其实是 AI/ML 算法的 易用性(Accessibility),以及如何将一些“真实世界”的结构(文本、图像、音频、视频)用向量的形式表示,并将其存储起来,以供应用实现一些有用的功能。有些人可能会说,把这些AI系统的输出(也就是所谓的“嵌入 Embedding”)放进数据存储系统中并不是什么新把戏。所以这里我们得再次强调,真正的新模式是 易用性:几乎所有应用都可以用这种近乎实时的方式查询并返回这些数据(文字图片音视频的向量表示)。

不过,这些与 PostgreSQL 有什么关系?那关系可大了!高效存储检索向量 —— 这种普适泛用数据类型,可以极大地简化应用程序开发,让相关联的数据都存放在同一个地方,并让人们继续使用现有的工具链。我们在十多年前的 JSON 上看到了这一点,现在我们在向量上也看到了这一点。

要理解为什么向量是新的 JSON,让我们回顾一下 JSON —— 互联网通信的事实标准,当 JSON 崭露头角时发生了什么?


JSON 简史:PostgreSQL 实现

在 “JSON崛起” 期间,我主要还是一名应用开发者。我正在构建的系统,要么是将 JSON 数据发送到前端,使其可以完成某种操作(例如渲染一个可更新的组件),要么是与返回 JSON 格式数据的“现代”API交互。JSON 的好处在于其简单性(很容易阅读和操作),作为一种数据交换格式具有很强的表达力。JSON 确实简化了系统间的通信,无论是从开发还是运维的角度。但我是希望在JSON中看到一些我喜欢的东西 —— 在数据库这一侧,我是使用模式(Schemas)的坚定支持者。

虽然 JSON 最初是作为一种交换格式而存在的,但人们确实会问 “为什么我不能直接存储和查询这玩意?” 这个问题引出了一种专门的数据存储系统 —— 可以用来存储和查询 JSON 文档。我确实试过好几种不同的 专用 JSON 存储系统,来解决一个特定场景下的问题,但我并不确定我是否想把他们引入到自己的应用技术栈中 —— 出于性能与可维护性的原因 (我不会说具体是哪些,因为十多年过去,时过境迁了)。这就引出了一个问题 —— 能否在PostgreSQL中存储 JSON 数据?

PostgreSQL JSON 特性矩阵

我记得当年去参加 PostgreSQL 活动时的急切心情 —— 等待 PostgreSQL 对原生 JSON 存储检索支持的更新。我记得当 PostgreSQL 9.2 增加了基于文本的 JSON 类型支持时自己是多么的激动开心。PostgreSQL 对 JSON 最开始的支持是对所存储 JSON 内容的合法性校验,以及一些用于提取 JSON 文档数据的函数与运算符。那时候并没有原生的索引支持,但如果你需要根据文档中的某个 Key 进行频繁查询,还是可以使用 表达式索引 功能来为你感兴趣的 Key 添加索引。

PostgreSQL 对 JSON 的初步支持帮助我解决了一些问题,具体来说有:对数据库中几个表的状态做快照,以及记录我与之交互的 API 的输出。最初的基于文本的 JSON 数据类型在检索能力上乏善可陈:你确实可以构建表达式索引来根据 JSON 文档中的特定 Key 来走索引,但实践上我还是会把那个 Key 单独抽取出来放在与 JSON 相邻的单独列中。

这里的关键在于:PG 对 JSON 的初步支持以 “JSON数据库”的标准来看还是很有限的。没错,我们现在可以存储 JSON,也拥有了一些有限的查询能力,但要和专用 JSON 数据库拼功能,显然还需要更多的工作。不过对于许多这样的用例,PostgreSQL仍然已经是足够好了:只要能和现有的应用基础设施一起使用,开发者还是愿意在某种程度上接受这些局限性的。PostgreSQL 也是第一个提供 JSON 支持的关系型数据库,带了一波节奏,最终直接导致 JSON 进入到 SQL 标准中。

俄罗斯的 PostgreSQL 与 Oleg 对 PG JSON 特性居功至伟

紧接着 PostgreSQL 作为 “JSON数据库” 的可行性,在 PostgreSQL 9.4 发布后出现质变:这个版本新增了 JSONB 类型,这是 JSON 数据类型的二进制表示,而且可以使用 GIN 索引来索引 JSON 文档中的任意数据。这让 PostgreSQL 能在性能上与专用 JSON数据库旗鼓相当,同时还能保留有关系数据库的所有好处 —— 尽管适应并支持这类应用负载花费了 PostgreSQL 好几年的时间。

PostgreSQL 对 JSON 的支持在过去的几年中持续发展演进,随着PostgreSQL不断实现和采纳 SQL/JSON 标准,未来也一定会继续保持这种发展势头。我曾与一些 PostgreSQL 用户聊过,他们在 PostgreSQL 数据库中存了几十TB的 JSON 文档 —— 用户表示体验甚好!

这个故事的关键是,开发者愿意押注 PostgreSQL 会拥有一个具有竞争力的 JSON存储系统,并愿意接受其最初实现的局限性,直到更为强大稳健的支持出现。这就引出了我们要讨论的 向量


向量崛起:一种新 JSON

向量并不是新东西,但近来它们的流行度飙升。如前所述,这归功于AI/ML系统新涌现出的易用性,而这些系统的输出结果是向量。典型用例是在存储的数据(文本、声音、视频)上建立模型,并用模型将其转换为向量格式,然后用于“语义搜索”。

语义搜索工作原理如下:你把输入用模型转换为对应的向量,并在数据库中查找与此向量最为相似的结果。相似度使用距离函数进行衡量:比如欧式距离,或余弦距离,结果通常会按距离排序取 TOP K,即 K 个最为相似的对象(K-NN, k nearest neighbors)。

向量的余弦距离被广泛用于衡量两者的相似度

用模型将“训练集”编码为向量需要耗费很长的时间,所以把这些编码结果 “缓存” 在持久化数据存储 —— 比如说数据库中是有意义的,然后你就可以在数据库中运行 K-NN 查询了。事先在数据库里准备好一组备查的向量,通常会为语义搜索带来更好的用户体验,需要“向量数据库”的想法就是这么来的。

AI模型将各种对象统一编码为向量(浮点数组)

在PostgreSQL中存储向量不是一件新鲜事儿。1996 年 PostgreSQL 首次开源时就已经带有数组类型(Array)了!而且多年来又进行了无数的改进。实际上,PostgreSQL 中 数组 类型名称可能有些用词不当,因为它其实可以存储多维数据(例如矩阵/张量)。PostgreSQL 原生支持了一些数组函数,不过有一些常见的向量运算不在其中,比如计算两个数组间的距离。你确实可以写个存储过程来干这个事,但这就是把活儿推给开发者了。

PostgreSQL特性矩阵:数组与Cube

幸运的是,cube 数据类型克服了这些局限。cube 在PostgreSQL代码库中也已经有20多年了,并且是为在高维向量上执行运算而设计的。cube 包含了在向量相似性搜索中使用的大多数常见距离函数,包括欧几里得距离,而且可以使用 GiST索引来执行高效的 K-NN 查询!但是 cube 最多只能存储100维的向量,而许多现代AI/ML系统的维度远超这个数。

ChatGPT Embedding API 使用 1536 维向量

那么,如果 array 可以搞定向量维度的问题但没有解决向量运算的问题;而 cube 可以搞定运算但搞不定维度,我们该怎么办?


PGVECTOR: 开源PG向量扩展

可扩展性 是 PostgreSQL 的基石特性之一:PostgreSQL 提供创建新数据类型和新索引方法的接口。这让 pgvector 成为可能:一个开源 PostgreSQL 扩展,提供了一种可索引的 vector 数据类型。简而言之,pgvector 允许您在 PostgreSQL 中存储向量,并使用各种距离度量执行K-NN查询:欧式距离、余弦和内积。到目前为止,pgvector 带有一种新索引类型 ivfflat,实现了 IVF FLAT 向量索引。

当您使用索引来查询向量数据时,事情可能和您所习惯的 PostgreSQL 数据查询略有不同。由于在高维向量上执行最近邻搜索的计算成本很高,许多向量索引方法选择寻找与正确结果 “足够接近” 的 “近似” 答案,这将我们带入 “近似最近邻搜索”(ANN)的领域。ANN 查询的关注焦点是,性能与召回率两个维度上的利弊权衡,这里“召回率(Recall)”指的是返回相关的结果所占百分比。

pgvector 在 ANN Benchmark 各测试集下的召回率/性能曲线

让我们以 ivfflat 方法为例。构建 ivfflat 索引时,您需要决定有多少个 list 。每个 list 代表一个“中心”,这些中心会使用 k-means 聚类算法确定。确定所有中心后,ivfflat 会计算每一个向量最接近哪个中心点,并将其添加到索引中。当查询向量数据时,你还需要决定需要检查多少个中心,这由 ivfflat.probes 参数确定。这就是您所看到的 ANN性能/召回率权衡:你检查的中心越多,结果就会越精确,但性能开销就越大。

IVF FLAT 索引算法的的召回率取决于检查的中心数量

把 AI/ML 的输出存入 “向量数据库” 已经很流行了,至于 pgvector 也已经有大把的使用样例。所以这里我们将关注重点放在未来的发展方向上。


迈向明天:更好的向量支持

与 PostgreSQL 9.2 版本中的 JSON 情况类似,我们正处于如何在 PostgreSQL 中存储向量数据的初级阶段 —— 虽然我们在PostgreSQL和 pgvector 中看到的大部分内容都很不错,但它即将要好得多!

pgvector 已经可以处理许多常见的 AI/ML 数据用例 —— 我已经看到许多用户成功地使用它开发部署应用!—— 因此下一步是帮助它打江山。这与 PostgreSQL 中的 JSON 和 JSONB 的情况没有太大区别,但 pgvector 作为一个扩展,将有助于它更快地迭代。

pgvector 的 Github Star 增长在2023年4月出现加速

在 2023 年的 PGCon 上,这是一个聚集了许多内部开发者的 PostgreSQL 会议,我做了一个名为《向量是新的JSON[1]》的快速演讲,其中分享了使用案例,以及改进 PostgreSQL 和 pgvector 向量数据检索性能所面临的挑战。这是一些需要解决的问题(有些已经在做了!):包括给 pgvector 添加更多并行机制,对超过 2000 维向量的索引支持,以及尽可能使用硬件来加速计算。好消息是添加这些功能并不难,只需要开源贡献!

许多人对于把 PostgreSQL 当成向量数据库这件事充满兴趣(重点是 PG 还是一个全能数据库!)。我预计正如历史上的 JSON 一样,PostgreSQL 社区会找到一种支持这种新兴工作负载的方法,更为安全,更容易伸缩扩展。

我期待您能提供各种反馈 —— 无论是关于PostgreSQL 本身还是 pgvector ,还是关于您如何在 PostgreSQL 中处理向量数据,或者您希望如何在 PostgreSQL 中处理数据,因为这将帮助社区为向量查询提供最佳的支持。

本文译自《VECTORS ARE THE NEW JSON IN POSTGRESQL[2]》一文。

作者 JONATHAN KATZ ,译者 冯若航


译者评论

PostgreSQL 在过去十年间有着持续稳定的高速增长,从一个"相对来说小众"的数据库,成为如今全世界开发者中最流行,最受喜爱,需求量最大的数据库,不可谓不成功。PG 成功的因素有很多,开源,稳定,可扩展,等等等等。但我认为这里的关键一招还是 JSON 支持。笔者本人就是在 PostgreSQL 9.4 为其强大 JSON 功能折服,果断从 MySQL 跳车弃暗投明。

PostgreSQL 获得数据库三项大满贯冠军,且势头一往无前

拥有了 JSON 特性的 PostgreSQL 等于 MongoDBMySQL 合二为一,恰到好处地赶上了互联网下半场的风口。从 DB-Engine 热度趋势上也能看出,PostgreSQL 开始起飞的时间正是在 2014 年 发布 PostgreSQL 9.4 之后。2013 ~ 2023 这十年可以说是 PG 的黄金十年,无数强大的新功能与各式扩展插件喷涌而出,奠定了 PG 现今不可撼动的地位。

DB-Engine 热度走势,来自搜索引擎与网站的综合指数

而放眼未来十年,数据库的下一站会是哪里?本文给出了答案 —— 向量。正如同 JSON 一样,PostgreSQL 永远站在时代浪潮的巅峰引领潮流 —— 成为第一个提供全方位向量支持的关系型数据库。我有充足的把握断言:以向量为代表的功能将在接下来的十年中继续驱动 PostgreSQL 的高速增长。

pgvector 一定不会是 PostgreSQL 处理向量数据的终点,但它为 SQL 向量处理设定了一个标杆。PGVector 项目由 Andrew Kane 于 2021年4月创建,慢热了两年,而从今年三四月开始半年不到暴涨 4K star。而我也可以骄傲的说,作为 PG 社区的一员,我也在这里推波助澜,做了一些工作。

我们将 pgvector 提入 PostgreSQL PGDG 官方源,正式成为 PG向量扩展的事实标准;我们进行性能评测,引发了推上关于 PGVector 的大讨论;而我们所维护的开箱即用的开源 RDS PG 替代 Pigsty,则是第一波将 pgvector 集成整合提供服务的 PostgreSQL 发行版

Pigsty 凝聚 PG 生态合力,为用户提供开源免费开箱即用的本地 PostgreSQL RDS 服务

目前我们也在着力于改进 pgvector 的实现,实现了另一种主流向量索引算法 hnsw,在一些 ANN 场景下相比 IVFFLAT 有20倍的性能提升,而且完全兼容 pgvector 接口,并将于近期 Pigsty Release 提供预览。

pgvector 改进实现在 ANN-Benchmark 下的初步表现

最重要的是,我们相信 PostgreSQL 社区的力量,我们愿意凝聚合力,劲往一处使,共同让 PostgreSQL 走得更快、更远,让 PostgreSQL 在 AI 时代再创辉煌!


References

[1] 向量是新的JSON

[2] VECTORS ARE THE NEW JSON IN POSTGRESQL

[3] AI大模型与向量数据库 PGVECTOR

[4] PostgreSQL:世界上最成功的数据库

[5] 更好的开源RDS替代:Pigsty

[6] Pigsty v2.1 发布:向量扩展 / PG12-16 支持

PostgreSQL:最成功的数据库

微信公众号原文 | 知乎原文

2023 年 StackOverflow 调研结果已经新鲜出炉,来自185个国家与地区的9万名开发者给出了高质量的反馈。 在今年的调研中,PostgreSQL 在数据库全部三项调研指标(流行度,喜爱度,需求度)上获得无可争议的全能冠军,成为真正意义上“最成功”的数据库 —— “PostgreSQL is the Linux of Database!”

https://demo.pigsty.cc/d/sf-db-survey

当我们说一个数据库“成功”时,究竟在说什么?评价一个数据库有许多标准:功能、质量、安全、性能、成本,但没有哪种可以普世泛用。不过 Succeed 既代表成功,又代表继承,所以成功与“后继有人”相通。对一项技术而言,用户的规模 、喜好、需求决定了生态的繁荣程度,唯有这种最终存在意义上的神意裁决 —— 才能让所有人心服口服。 而连续进行七年的 StackOverflow 年度开发者调研为我们窥见技术发展流行趋势打开了一扇窗户。

PostgreSQL现在是全世界最流行的数据库

PostgreSQL是开发者最喜爱欣赏的数据库!

PostgreSQL是用户需求最为强烈的数据库!

流行度代表过去,喜爱度代表现在,需求度代表将来,这三个指标很好地反映了一项技术的生命力。存量与增量,时与势都站在 PostgreSQL 一侧,恐怕在几年内恐怕都不会有任何能挑战 PostgreSQL 地位的竞争对手。 作为 PostgreSQL 忠实的用户,社区成员,专家,布道师与贡献者,从拥抱 PostgreSQL的那一刻起,我就相信会有这一天,然而亲自见证这一刻,仍然让我感慨良多。遂撰此文,聊一聊这件事背后的 WhyWhat

推荐阅读:StackOverflow 2022 往期调研结果回顾:《为什么PostgreSQL将成为最成功的数据库?


数据的来源:社区调研

数据库的用户是开发者,而没有比直接问开发者们更有代表性的调研方式了。StackOverflow 调研结果中提供了 流行,欣赏,渴望三个结果指标,但这三项数据都来自同一个巧妙设计的问卷题目:

“在过去一年中,您在哪些数据库环境中进行了密集的开发工作,您又希望在接下来一年在哪些数据库上工作?如果你过去一年用了这个数据库,来年还希望接着用,那么就在两个复选框上都打勾”。

“Which database environments have you done extensive development work in over the past year, and which do you want to work in over the next year? If you both worked with the database and want to continue to do so, please check both boxes in that row.”

每个数据库后都有两个复选框,如果开发者在第一个框上打勾,即去年我在用此数据库,那么就会被标记为“使用者”(Used); 如果开发者在第二个框上打勾,即来年我想用这个数据库,那么会被标记为“需求者”(Wanted);而两个框都打勾的开发者,会被标记为“赞赏者”(Loved / Admired)。

https://survey.stackoverflow.co/2023

使用者占总体的比例,就是流行度,或使用率,在上图左边用柱状图表示。需求者占总体的比例,就是需求度,或渴望度,在上图右边以蓝点表示。 赞赏者占现有使用者的比例,就是欣赏度,或喜爱度/口碑,在上图右边以红点表示。不难看出,2023年,PostgreSQL 在流行度上甩开 MySQL,成为世界上最流行的数据库。在需求度和口碑上更是远远甩开其他数据库独树一帜。

同样的问题连续问了七年,如果我们结合这过去七年的变迁,把排名前10的主流数据库流行度 - 净喜爱度画在一张二维散点图上,那么就能更容易地获得一些关于数据库领域的发展变迁的洞察,对形成正确的比例感很有帮助。

X轴为流行度,Y轴为净喜爱程度(2*喜爱度% - 100),图元大小与流行度与喜爱度的几何平均数成正比。

在 2023年的当下切面中,四个角落被四种数据库占据:右上角是最为流行且最受欢迎的 PostgreSQL,右下角是流行但不受待见的 MySQL; 左上角是流行程度一般但备受喜爱的 Redis,左下角是过气且不受待见的 Oracle。在四者中间,坐落着相对中庸的 SQLiteMongoDBSQL Server

结合时间轴不难看出,PostgreSQL 的流行程度与受欢迎程度在持续增长;MySQL 的受欢迎程度变化不大但流行度暴跌; Redis 与 SQLite 整体上在进步,而 MongoDB 开始见顶回落,SQL Server 和 Oracle 这两种商业关系型数据库最近几年都在持续走下坡路。

从图中我们可以得出一个基本的判断:在未来几年中,数据库领域都不会出现足以挑战 PostgreSQL 的对手。PostgreSQL 在数据库领域的地位,已经如同 Linux 在服务器操作系统上的地位一样难以撼动


过去的积累:流行度

PostgreSQL —— 世界上最流行的数据库

一项技术使用者占总体的比例,就是流行度。它的含义是:过去一年有多少比例的用户使用了这项技术。流行度代表过去一年的积累使用,是存量指标,也是最核心的事实指标。

在 2023 年, “最先进” PostgreSQL 在所有开发者中以 45.6% 的使用率,首次超过“最流行”数据库 MySQL 41.1%,领先 4.5%,使用率是第二名 MySQL 的1.1倍。 对于专业开发者(约占总样本的3/4)来说,PostgreSQL 的使用率在去年(2022)就已经超过 MySQL 了,以 46.5% vs 45.7% 领先0.8个百分点; 在 2023 年,这一差距进一步拉大到 49.1% vs 40.6,领先 8.5% —— 换句话说,专业开发者中,PostgreSQL 的使用率已经是 MySQL 的 1.2 倍了。

过去几年,MySQL 一直霸占着数据库流行榜的榜首,洋洋得意地打起了“世界上最流行的开源关系型数据库” 这一旗号。 不过这次,“最流行” 的桂冠真的要让给 PostgreSQL 了。在流行度上,其他数据库和 PostgreSQL / MySQL 比根本就不是一个重量级,自然就更不用说了。

更重要的的是变化趋势:在长期列入排名的十几款头部数据库中,只有 PostgreSQL 的流行度是持续上升的,保持着高歌猛进的增长势头,而其他所有的数据库使用率都在下行。 此消彼长,随着时间的推移,PostgreSQL 与其他数据库的流行度差距只会进一步拉大 —— 因此在相当长的一段时间内,恐怕是看不到有任何挑战者能撼动 PostgreSQL 现在的位置了。

值得一提的是,“国产数据库”的标杆 ”TiDB“ 这次也加入到 StackOverflow 排行榜中,并以 0.2% 的使用率,拿到了末位第 32 名的名次。

流行度反映的是当下数据库的规模势能,而喜爱度反映的是未来数据库的增长潜能。


现在的动能:喜爱度

PostgreSQL —— 最受开发者喜爱的数据库

所谓“口碑”,喜爱度(Loved)或欣赏度(Admired),指的是有多少比例的用户愿意继续使用此项技术,这是一个年度的“留存率”指标,可以反映用户对一项技术的看法与评价。

2023 年, PostgreSQL 蝉联最受开发者喜爱的数据库。过去几年 Redis 一直是用户最喜欢的数据库。直到 2022 年,PostgreSQL 第一次超过 Redis,成为最受开发者喜爱的数据库。 PostgreSQL 和 Redis 的口碑一直在伯仲之间(70%),并与其他后来者拉开了非常显著的差距。

作为一个交叉印证,在 2022 PostgreSQL 社区年度调研中,对于 PostgreSQL 的存量用户来说,使用程度加深,用量加大的比例(蓝/粉)对于用量萎缩的比例(黄绿)占据了压倒性多数,足以说明基本盘留存的稳定程度。

Redis是简单易用的数据结构缓存服务器,经常会与关系型数据库 PostgreSQL 搭配使用,广受开发者喜爱(但流行度一般,只有20%,位列第六)。 在后面的交叉分析环节我们也可以看到这两者之间有着所有数据库间最为强烈的羁绊 —— 86% 的 Redis 用户想要使用 PostgreSQL,而 30% 的 PostgreSQL 用户想要使用 Redis。 其他评价正面的数据库包括:SQLite,MongoDB,SQL Server 等。MySQL 和 ElasticSearch 的口碑在 50% 中线算毁誉参半。榜上最不受用户待见的数据库为 Access、 IBM DB2 、CouchDB,Couchbase,以及 Oracle。

并不是所有潜能,都可以转换为实打实的动能。用户的喜爱并不一定会付诸行动,而这就是第三项指标所要回答的问题 —— 需求度。


未来的趋势:需求度

PostgreSQL —— 需求量最大的数据库

需求者占总体的比例,就是需求率(Wanted),或渴望度(Desired)。它的含义是,接下来一年有多少比例的用户会实际选择使用此项技术。 在需求度 / 渴望度 这一项中,PostgreSQL 一骑绝尘,远远甩开其他数据库。以 42.3% 的比例连续第二年获得第一,且保持着一往无前的增长态势。不断与后来者拉开距离。

在 2023 年,一些数据库的需求量出现了显著增长。大概率是因为由 OpenAI ChatGPT 所引领的大语言模型AI浪潮所致:对智能的需求拉动了对数据基础设施的需求。 10年前,对 JSONB/GIN 等 NoSQL 特性的支持奠定了 PostgreSQL 在互联网黄金时代的蓬勃发展,而今天,第一个构建在成熟数据库上的向量扩展 pgvector ,更是让 PostgreSQL 有了进入 AI 时代的船票,为下个十年的增长准备好了敲门砖。


但是,为什么呢?

PostgreSQL 在需求率, 使用率,喜爱率上都拔得头筹,天时地利人和齐备,动能势能潜能都有,足以称得上是最成功的数据库,而且在肉眼可见的几年里也不会有任何挑战者。 但令人好奇的是,为什么 PostgreSQL 会如此成功 ? 其实,秘密就藏在它的 Slogan 里:“世界上最先进的开源关系型数据库

关系型数据库是如此的普及与重要,也许其他的数据库品类如键值,文档,搜索引擎,时序,图,向量加起来也比不上它的一个零头。以至于当大家谈起数据库时,如果没有特殊说明,默认隐指的就是”关系型数据库“。在它面前,没有其他数据库品类敢称自己为”主流“。 在去年的《为什么PostgreSQL将成为最成功的数据库?》中,我们详细介绍了关系型数据库的竞争格局 —— 三足鼎立:关系型数据库的生态位高度重叠,其关系可以视作零和博弈。抛开微软生态关门自嗨相对独立的商业数据库 SQL Server 不提,在当下分久必合的收敛阶段中,以 WireProtocol 计能作为“根”的数据库只有三种:Oracle,MySQL,以及PostgreSQL。关系型数据库世界里上演的是一场 三国演义

今天下三分,然 Oracle/MySQL 疲敝 ,日薄西山, PostgreSQL 高歌猛进,如日中天。此消彼长,前途无量。

Oracle 有才无德,MySQL 才浅德薄,PGSQL 德才兼备”

Oracle 是老牌商业数据库,有着深厚的历史技术积淀,功能丰富,支持完善。广受不差钱且需要背锅侠的企业,特别是金融行业喜爱。但其费用高昂,且以讼棍行径成为知名的业界毒瘤。 Microsoft SQL Server 性质与Oracle类似,都属于商业数据库。商业数据库整体受开源数据库冲击,处于缓慢衰退的状态。

MySQL 号称“最流行”,然而树大招风:前有狼后有虎,上有野爹下有逆子,处于四面楚歌的境地中: 在严谨的事务处理和数据分析上,MySQL 被同为开源生态位的 PostgreSQL 甩开几条街;而在糙猛快的敏捷方法论上,MySQL 又不如新兴 NoSQL 好用; 上有养父 Oracle 压制,中有兄弟 MariaDB 分家,下有逆子 TiDB/OB 等兼容 NewSQL 分羹,因此也在走下坡路。

Oracle 作为老牌商业数据库,才毋庸质疑;但其作为业界毒瘤,“德” ,亦不必多说,故曰:“有才无德”。 MySQL 虽有开源之功德,奈何认贼作父;且才疏学浅,功能简陋,只能干干CRUD,故曰:“才浅德薄”。 唯 PostgreSQL德才兼备:既占据了开源崛起之天时,又把握了最为流行之地利,还有着先进稳定之人和。 正所谓:君子藏器于身,因时而动。不鸣则已,一鸣惊人!


开源与先进

来自 TimescaleDB 的PostgreSQL 社区年度调研也反映出,用户选择 PostgreSQL 的首要因素便是 开源稳定开源 —— 意味着软件本身可以免费使用,可以二次开发,没有供应商锁定,不存在“卡脖子问题”。 可靠 —— 意味它能正确稳定工作,行为表现能够符合预期,而且有着长时间大规模生产环境的优异战绩。越是资深的开发者,便越是看重这两个属性。

宽泛地讲,扩展,生态,社区,协议可以归并入 “开源” 。而稳定可靠,ACID,SQL,扩展,可用性,可以总结为 “先进” 。这便正好与 PostgreSQL 的 Slogan 相呼应 —— 世界上最先进的开源关系型数据库

https://www.timescale.com/state-of-postgres/2022


开源之德

PG的“德”在于开源。祖师爷级的开源项目,全世界开发者群策群力的伟大成果。协议友善BSD,生态繁荣扩展多。开枝散叶,子孙满堂,Oracle替代扛旗者.

什么叫“德”,合乎于“道”的表现就是德。而这条“道”就是开源。PostgreSQL是历史悠久的祖师爷级开源项目,更是全世界开发者群策群力的典范成果。

很久很久以前,开发软件/信息服务需要使用非常昂贵的商业数据库软件。单花在软件授权上的费用可能就有六七位数,加之相近的硬件成本与服务订阅成本。Oracle一个 CPU 核一年的软件授权费用便高达十几万,壕如阿里也吃不消要“去IOE”。以 PostgreSQL / MySQL 为代表的的开源数据库崛起,让世界多了一个新的选择。

“不要钱” 的开源数据库可以让我们自由随意地使用数据库软件,而这一点引发了行业变革:从上万元每核·每月的商业数据库软件授权,到20块钱/核·月的纯硬件成本。数据库走入了寻常企业中,让免费提供信息服务成为可能。

开源是有大功德的:互联网的历史就是开源软件的历史,IT行业之所以有今天的繁荣,人们能享受到如此多的免费信息服务,核心原因之一就是开源软件。 开源是一种真正成功的,以软件自由为目的,由开发者构成的 Communism(社区主义软件这种IT业的核心生产资料变为全世界开发者公有,按需分配。开发者各尽所能,人人为我,我为人人。

一个开源程序员工作时,其劳动背后可能蕴含的是数以万计顶尖开发者的智慧结晶。程序员薪资高从原理上来说是因为,开发者本质上不是一个简单的工人,而是一个指挥软件和硬件干活的 包工头。程序员自己就是核心生产资料;软件来自公有社区;服务器硬件更是唾手可得;因此一个或几个高级的软件工程师,就可以很轻松地利用 开源生态快速解决领域问题。

通过开源,所有社区开发者形成合力,极大降低了重复造轮子的内耗。使得整个行业的技术水平以匪夷所思的速度向前迈进。开源的势头就像滚雪球,时至今日已经势不可挡。 越是底层基础的软件,开源便越占据主导优势。基本上除了一些特殊场景和路径依赖,软件特别是基础软件中,闭门造车/所谓“自力更生”已经成了业内超级大笑话。

开源,是 PostgreSQL 对阵 Oracle 的最大底气所在。

Oracle 先进,但 PostgreSQL 也不差。PostgreSQL 是 Oracle 兼容性最好的开源数据库,原生即支持 Oracle 85% 的功能,更有 96% 功能兼容的专业发行版。 但更重要的是,Oracle 价格高昂,而 PG 开源免费。压倒性的成本优势让 PG 拥有了巨大的生态位基础:它不一定要在功能先进性上超过Oracle 才能成功 ,廉价9成正确 已经足以干翻 Oracle 。

PostgreSQL 可以视作一个开源版的“Oracle”,是唯一能真正威胁到 Oracle 的数据库。作为 ”去O“ 抗旗者,PG 可谓子孙满堂,养活了一大批自主可控 的国产数据库公司。 根据信通院统计,36% 的 “国产数据库” 直接基于PG “二开/魔改/套壳/换皮”,华为的openGauss 与 GaussDB 就是最典型的例子。 重要的是,PostgreSQL 使用 BSD-Like 的 PostgreSQL 协议,是允许这种行为的 —— 你只要不打着PG的名号招摇撞骗,改个名字直接卖起来都行。这样开放的胸襟,是被Oracle收购的,使用GPL协议的 MySQL 所难以比拟的。


先进之才

PG的“才”在于先进。一专多长,全栈多模:“自主可控自动驾驶时序地理空间AI向量分布式文档图谱全文检索可编程超融合联邦流批一体 HTAP Serverless 全栈式平台数据库”,单一组件即可覆盖几乎所有数据库需求。

PostgreSQL 不仅仅是传统意义上只能做 OLTP 的单纯 “关系型数据库”,而是一个多模态数据库。 对于中小企业来说,基本单一组件便足以覆盖中小型企业绝大多数场景的数据需求:OLTP,OLAP,时序,地理空间GIS,分词与全文检索,JSON/XML文档,NoSQL特性,图,向量,全都能用上。

皇帝数据库 —— 自主可控自动驾驶时序地理空间AI向量分布式文档图谱全文检索可编程超融合联邦流批一体 HTAP Serverless 全栈式平台数据库

PostgreSQL 的先进,除了体现在其备受赞誉的内核稳定性上,更是体现在它强大的可扩展性里。 插件系统让 PostgreSQL 不再仅仅是一个单线程演化的数据库内核,而是可以有无数并行演进的扩展插件,如同量子计算一般同时探索所有方向上的可能性。每一个数据处理的细分垂直领域,PostgreSQL 绝不会缺席。

正如:PostGIS 之于地理时空数据库,TimescaleDB 之于时序数据库,Citus 之于分布式/列存储/HTAP数据库,PGVector 之于AI向量数据库,AGE之于图数据库,PipelineDB 之于流处理; 以及终极杀招 —— 使用外部数据源包装器(FDW),使用统一的 SQL 访问所有异构的外部数据库。可以说PG是真正的全栈数据库平台,比起 MySQL 这样单纯的 OLTP 数据库,它的功能要先进太多了。

在一个很可观的规模内,PostgreSQL 都可以独立扮演多面手的角色,一个组件当多种组件使。而单一数据组件选型可以极大地削减项目额外复杂度,这意味着能节省很多成本。它让十个人才能搞定的事,变成一个人就能搞定的事。 在使用“专用数据库”前切莫忘记:为了不需要的规模而设计是白费功夫,这属于过早优化的一种形式。如果真有那么一样技术可以满足你所有的需求,那么使用该技术就是最佳选择,而不是试图用多个组件来重新实现它。

以探探为例,在 250w TPS200 TB 不重复TP数据的量级下,单一PostgreSQL选型依然能稳定可靠地撑起业务,并能在很可观的规模内做到一专多长。 除了本职的 OLTP,PG 还在相当长的时间里兼任了缓存,OLAP,批处理,甚至消息队列的角色。当然神龟虽寿,犹有竟时。最终这些兼职功能还是要逐渐分拆出去由专用组件负责,但那已经是近千万日活时候的事了。

PostgreSQL 的先进,更是体现在其繁荣的生态里。以数据库内核为中心,向上,有着衍生特化的变体与构建于其上的“上层数据库” —— Greenplum数据仓库,Firebase的开源替代 Supabase,专用图数据库 edgedb 等等等等。 向下,有着各种开源/商业/云发行版来整合各种工具形成合力 —— 各家的RDS ,开箱即用的 Pigsty ;水平方向上,甚至还有着一些强大的拟态组件/版本,可以通过兼容 Wire Protocol 的方式来仿真其他数据库,无需修改客户端驱动就能完成数据库迁移 —— 模拟 SQL Server 的 babelfish,模拟 MongoDB 的 FerretDB,兼容 Oracle 的 EnterpriseDB / IvorySQL 都是样例。

PostgreSQL 的先进性有目共睹,这也是其对阵同为开源关系型数据库的老对手 —— MySQL 时,真正的核心竞争力。

先进,是 PostgreSQL 压倒 MySQL 的核心竞争力。

MySQL的口号是“世界上最流行的开源关系型数据库”,它的核心特点是糙猛快,基本盘是互联网公司。互联网公司的典型特点是什么?追逐潮流糙猛快 说的是互联网公司业务场景简单(CRUD居多);数据重要性不高,不像传统行业(例如银行)那样在意数据的一致性与正确性;可用性优先,相比停服务更能容忍数据丢乱错,而一些传统行业宁可停止服务也不能让账目出错。 说的则是互联网行业数据量大,它们需要的就是水泥槽罐车做海量 CRUD,而不是高铁和载人飞船。 说的则是互联网行业需求变化多端,出活周期短,要求响应时间快,大量需求的就是开箱即用的软件全家桶(如LAMP)和简单培训就能上手干活的 CRUD Boy。 于是,糙猛快的互联网公司和糙猛快的 MySQL 一拍即合,MySQL吃到了互联网崛起的一波大红利。

然而时来天地皆同力,运去英雄不自由。时过境迁,PostgreSQL 进步神速,在”快“与”猛“上 MySQL 已经不占优,现在只剩下”“了。

MySQL竟然默认允许部分成功的事务提交

先进的因会反映为流行的果,流行的东西因为落后而过气,而先进的东西会因为先进变得流行。在这个变革的时代中,没有先进的功能打底,“流行”也也难以长久。时代所赋予的红利,也会随时代过去而退潮。 调查的结果也用事实证明,MySQL 唯一能引以为豪的 “流行” 在 PostgreSQL 压倒性的 “先进” 优势前,根本维持不住。

先进开源,就是 PostgreSQL 成功的最大法宝。Oracle 先进, MySQL 开源,PostgreSQL 先进又开源。天时地利人和齐备,何愁大业不成?


展望未来

PostgreSQL 数据库内核在数据库领域的生态位,类似于 Linux 操作系统内核在操作系统领域的生态位。 对于数据库,至少是 OLTP 数据库来说,数据库内核之争已经尘埃落定 —— PostgreSQL 已经是一台足够完美的内核发动机。

然而,用户最终需要的不单单是一台发动机,而是整车、驾驶能力与交通服务。数据库领域竞争的焦点,已经从 Software 本身,转移到了 Software enabled Service —— 完整的数据库发行版与数据库服务。 对于基于 PostgreSQL 内核的数据库发行版而言,竞争才刚刚开始。谁会成为PG的Debian,RedHat 与 Ubuntu ? 这便是我们做 Pigsty 的初衷 —— 制作一个开箱即用的、开源免费、本地优先的 PostgreSQL 数据库发行版,让所有人都能用好数据库用好数据库。 当然,限于篇幅,那就是另一篇要介绍的故事了。


参考阅读

2022-08 《PostgreSQL 到底有多强?

2022-07 《为什么PostgreSQL是最成功的数据库?

2022-06 《StackOverflow 2022数据库年度调查

2021-05 《Why PostgreSQL Rocks!

2021-05 《为什么说PostgreSQL前途无量?

2018 《PostgreSQL 好处都有啥?

2023 《更好的开源RDS替代:Pigsty

2023 《StackOverflow 7年调研数据跟踪

2022 《PostgreSQL 社区状态调查报告 2022

PostgreSQL 到底有多强?

微信公众号原文 | 知乎原文

上一回,我们通过分析 StackOverflow 的用户调研数据,说明了《为什么PostgreSQL是最成功的数据库》。

而这一次我们将用性能数据来说话,聊聊最成功的 PostgreSQL 到底有多强,帮助大家做到“心中有数”。


太长不看

如果您对以下这些问题有兴趣,那么本文会对您有所帮助:

  • PostgreSQL 到底性能有多强? 点查 QPS 60万+,最高达 200 万。读写 TPS (4写1读)每秒 7 万+,最高达14万。
  • PostgreSQL 与 MySQL 的极限性能对比 极限条件下,PgSQL点查性能显著压倒 MySQL,其他性能基本与MySQL持平。
  • PostgreSQL 与其他数据库的性能对比 “分布式数据库”/NewSQL 在相同硬件规格下的性能表现显著落后于经典数据库。
  • PostgreSQL 与其他分析数据库的 TPC-H 表现。 PostgreSQL 原生作为一个 HATP 数据库,有比较亮眼的分析表现。
  • 云数据库 / 云服务器 的成本到底有没有优势? c5d.metal 用1年的价格,可以把服务器买下来托管用5年。对应规格云数据库用1年的价格,可以供你买同样的EC2用20年

详细测试过程与原始数据放置于:github.com/Vonng/pgtpc


PGBENCH

软件与硬件的技术日新月异,尽管性能评测的文章汗牛充栋,却没有多少能反映这些变换。在这项测试中,我们选择了两种新规格硬件,使用 PGBENCH 测试了最新的 PostgreSQL 14.5 在这些硬件上的性能表现。

测试的主体包括四种规格的硬件,两台 Apple 笔记本与三台 AWS EC2云服务器,分别是 2018 年使用 Intel 6核 i9芯片的 15寸顶配 Macbook Pro,2021 年使用 M1 MAX 芯片的顶配 16 寸 Macbook Pro ,AWS z1d.2xlarge (8C 64G),以及 AWS c5d.metal ,这些都是市面上可以轻松买到的商用硬件。

PGBENCH是 PostgreSQL 自带的压测工具,默认使用类 TPC-B 的查询,可用于评估 PostgreSQL 及其兼容版数据库的性能。测试分为两种:只读查询 RO、以及读写 RW。只读查询包含一条 SQL,随机从1亿条数据库中挑选一条查出;而读写事务包含5条SQL语句,一条查询、1条插入与三条更新。测试基于 s=1000 的数据集规模,使用 PGBENCH 逐步增加客户端连接数,找到 QPS / TPS 的极大值点,并记录持续测试 3-5 分钟后的稳定均值,结果如下:

No Spec Config CPU Freq S RO RW
1 Apple MBP Intel 2018 Normal 6 2.9GHz - 4.8GHz 1000 113870 15141
2 AWS z1d.2xlarge Normal 8 4GHz 1000 162315 24808
3 Apple MBP M1 Max 2021 Normal 10 600MHz - 3.22GHz 1000 240841 31903
4 AWS c5d.metal Normal 96 3.6GHz 1000 625849 71624
5 AWS c5d.metal Extreme 96 3.6GHz 5000 1998580 137127

Read Write

pg-performence-2.jpg

图:各硬件配置下读写 TPS 上限

pg-performence-3.png

图:各硬件配置下读写 TPS 曲线

Read Only

pg-performence-4.png

图:各硬件配置下点查 QPS 上限

pg-performence-5.png

图:各硬件配置下点查 QPS - 并发曲线

结果相当令人震惊,在 Apple M1 Max 10C 笔记本上,PG 跑出了 32K 读写,240K 点查的性能水平,在 AWS c5d.metal 生产物理机上,PG 跑出了 72K 读写,630K 点查的性能。使用极限优化压榨,最多可以达到 单机 137K 读写,2M 点查 的怪兽级性能。

作为一个粗略的规格参考,探探作为一个前部的互联网App,PostgreSQL 全局 TPS 为 40万左右。这意味着十几台这样的新笔记本,或几台顶配服务器(10W内¥)就有潜力支撑起一个大型互联网应用的数据库服务,这对于以前来说是难以想象的。

关于成本

以宁夏区域,C5D.METAL 机型为例,该机型是目前综合算力最好的物理机,且自带 3.6 TB的本地NVME SSD存储,有7种可选的付费模式:

付费模式 月度 预付 折合每年
按需付费 31927 0 383,124
标准预留,1年,无预付费用 12607 0 151,284
标准预留,1年,预付部分 5401 64,540 129,352
标准预留,1年,预付全部费用 0 126,497 126,497
可转化预留,3年,无预付费用 11349 0 136,188
可转化预留,3年,预付部分 4863 174,257 116,442
可转化预留,3年,预付全部费用 0 341,543 113,847

折合每年成本在 11万 ~ 15万,零售按需每年成本38万。该机器如果自行购置,IDC托管代维网电五年综合成本应在10万内。尽管看上去云硬件的年化成本高达自建的五倍,但考虑到其灵活性,折扣优惠与抵扣券,AWS EC2 云服务器定价总体仍处于合理范围。使用此类云硬件自建数据库,也有非常优异的性能表现。

但 RDS for PostgreSQL 则完全是另一个故事了,如果您想使用类似规格的云数据库,最接近的规格是 db.m5.24xlarge,96C,384G,配置 3.6T / 80000 IOPS 的 io1存储(c5d.metal 3.6T NVME SSD 8K RW IOPS 大约95K左右,普通 io1 存储最高 IOPS 为 80K),则每月成本为 24万¥,每年成本为286,7630¥ ,是同规格 EC2 自建的近 20 倍

AWS价格计算器:https://calculator.amazonaws.cn/


SYSBENCH

PostgreSQL 确实很强,但与其他数据库系统相比则何如?PGBENCH 主要用于评估 PostgreSQL 及其衍生/兼容数据库的性能,但如果需要横向比较不同数据库的性能表现,我们就要用到 sysbench 了。

sysbench 是一款开源、跨平台的多线程数据库性能测试工具,测试结果可以很有代表性地反映一个数据库系统的事务处理能力能力。sysbench 包含了10个典型测试用例,如测试点查性能的 oltp_point_select,更新性能的 oltp_update_index,综合读写事务性能的 oltp_read_only (16条查询一个事务),oltp_read_write (20条混合查询一个事务)与oltp_write_only (6条写入SQL)等…。

sysbench 既可以用于测试 MySQL 的性能,也可以用来测试 PgSQL 的性能(当然也包括两者的兼容衍生),因此具有良好的横向可比性。让我们先来看一下最为喜闻乐见的对比,开源关系数据库内战:世界上“最流行”的开源关系型数据库 —— MySQL , 与世界上最先进的开源关系型数据库 —— PostgreSQL 性能横向对比。

Dirty Hack

MySQL 并没有提供一个官方的 sysbench 测试结果,只是在官网上贴出了一个第三方评测结果的图片与链接,不加解释地暗示 MySQL 可以做到 1M 的点查 QPS,240K 的索引键更新,约 39K 的复合读写TPS。

pg-performence-5.png

图:https://www.mysql.com/why-mysql/benchmarks/mysql/

这是相当不讲武德的行为。因为如果阅览了连接的评测文章就会发现:这是把所有 MySQL 安全特性关闭得到的结果:关闭Binlog,提交刷盘,FSYNC,性能监控,DoubleWrite,校验和,强制使用 LATIN-1 字符集,这样的数据库根本没法用于生产环境,只是为了刷分而刷分。

但反过来说,我们也可以使用这些 Dirty Hack,把对应的 PostgreSQL 安全特性也关闭,也看看 PostgreSQL 的最终极限在哪里?结果相当震撼,PGSQL点查QPS干到了 233万每秒,峰值远远甩开 MySQL 一倍还多。

pg-performence-6.png

图:不讲武德的Benchmark:PgSQL vs MySQL

pg-performence-7.png

PostgreSQL 极限配置下点查压测现场

必须说明的是,MySQL 的bench使用的是 48C 2.7GHz的机器,而PostgreSQL使用的是 96C 3.6GHz 的机器。不过因为PG使用进程模型,我们可以使用 c=48 的测试值作为 PG 在 48C 机器上表现的一个下限近似:对于只读请求,QPS峰值通常在客户端数略大于CPU核数时达到。即便如此,c=48 时PG的点查 QPS( 150万)仍然比MySQL峰值高了43%。

在此也期待 MYSQL 专家基于完全相同的硬件给出测评报告,更好的地进行对比。

pg-performence-8.png

图:MySQL 有结果的四项 sysbench 结果,c=48

在其他测试上,MySQL 也有不错的极限表现,otlp_read_only, oltp_update_non_index 都与 PostgreSQL (c=48)接近持平,甚至在 oltp_read_write 上还略微超过 PostgreSQL。

总体来说在极限条件下,PG除了点查上碾压了MySQL,其他测试上性能与 MySQL 基本持平。

Fair Play

尽管在功能丰富度上判若云泥,但 MySQL 在极限性能上基本能与 PostgreSQL 称得上大体旗鼓相当。那么其他的数据库,特别是新一代 NewSQL 的表现又如何呢?

能够在官网上给出 sysbench 测试报告的数据库都算是 Fair Play 的体面玩家,我们相信他们都是基于真实生产环境使用的配置进行的测试,因此不能和 MySQL 那样使用 Dirty Hack。这里我们依然使用 AWS c5d.metal 机型,但完全使用生产环境配置进行性能测试,相比极限性能有接近一半折损,但更为费厄泼赖,具有很强的可对比性。

我们从几种比较具有代表性的NewSQL数据库官网上收集到了官方的 sysbench 评测报告。并不是所有的数据库都给出了完整的 sysbench 10 项测试结果,而且硬件规格与表规格也参差不齐。不过考虑到几种数据库均使用基本相仿的硬件规格(100核上下的算力,PolarDB-X , YugaBytes 除外),数据规模也基本为 160M 记录(OB,YB除外),总体还是具有比较可观的横向可比性,也足以让我们管中窥豹形成直觉认知了。

Database PGSQL.C5D96C TiDB.108C OceanBase.96C PolarX.64C Cockroach Yugabyte
oltp_point_select 1372654 407625 401404 336000 95695
oltp_read_only 852440 279067 366863 52416
oltp_read_write 519069 124460 157859 177506 9740
oltp_write_only 495942 119307 9090
oltp_delete 839153 67499
oltp_insert 164351 112000 6348
oltp_update_non_index 217626 62084 11496
oltp_update_index 169714 26431 4052
select_random_points 227623
select_random_ranges 24632
Machine c5d.metal m5.xlarge x3 i3.4xlarge x3 c5.4xlarge x3 ecs.hfg7.8xlarge x3 ecs.hfg7.8xlarge x1 Enterprise c5d.9xlarge x3 c5.4xlarge x3
Spec 96C 192G 108C 510G 96C 384G 64C 256G 108C 216G 48C 96G
Table 16 x 10M 16 x 10M 30 x 10M 1 x 160M N/A 10 x 0.1M
CPU 96 108 96 64 108 48
Source Vonng TiDB 6.1 OceanBase PolarDB Cockroach YugaByte

pg-performence-10.png

图:sysbench 10项测试结果(QPS,越高越好)

pg-performence-11.png

按数据库分类,除以核数的归一化性能对比

让人感到震惊的是,新一代分布式数据库(NewSQL)全线拉胯。在相近的硬件规格下,与 PostgreSQL 表现出高达数量级的差距,几种新数据库中表现最好的反而是仍然基于经典主从架构的 PolarDB。这样的性能结果,难免不让人重新审视起分布式数据库与 NewSQL 的理念

通常来说,分布式数据库的核心利弊权衡是质量换规模,但让人没想到的是牺牲掉的不仅仅是功能与稳定性,还有如此可观的性能。高德纳曰:“过早优化是万恶之源”,为了不需要的规模(万亿级+,TP百TB+)牺牲如此大的性能(以及功能与稳定性)毫无疑问是过早优化的一种形式,而能有多少业务场景会有 Google 量级的数据非要分布式数据库不可,仍然是一个问号。


TPC-H分析性能

TP不行,AP来凑。尽管分布式数据库在 TP 领域如此拉胯,但数据分析 AP 才是分布式数据库的基本盘,因此很多分布式数据库喜欢炒作 HTAP 的概念。而衡量 AP 系统的能力,我们会用到 TPC-H 测试。

TPC-H 是一个模拟数仓,包含8张数据表,与22条复杂分析类SQL。衡量分析性能的标准通常是在指定仓数下执行这22条SQL的耗时。通常使用100仓,约100GB数据作为基准。我们在本地笔记本和小型AWS云服务器进行了 TPC-H 1,10,50,100 仓的测试,完成全部22个查询,耗时结果如下:

Scale Factor Time (s) CPU Environment Comment
1 8 10 10C / 64G apple m1 max
10 56 10 10C / 64G apple m1 max
50 1327 10 10C / 64G apple m1 max
100 4835 10 10C / 64G apple m1 max
1 13.5 8 8C / 64G z1d.2xlarge
10 133 8 8C / 64G z1d.2xlarge

作为横向对比,我们选取了一些其他数据库官网或比较详细的第三方测评结果。不过在对比前,有几点需要注意:一是有一些数据库产品仓数并非100,二来硬件规格也不尽相同,三来并不是所有数据库评测结果都来自原厂,因此只能作为大致的对照和参考

Database Time S CPU QPH Environment Source
PostgreSQL 8 1 10 45.0 10C / 64G M1 Max Vonng
PostgreSQL 56 10 10 64.3 10C / 64G M1 Max Vonng
PostgreSQL 1327 50 10 13.6 10C / 64G M1 Max Vonng
PostgreSQL 4835 100 10 7.4 10C / 64G M1 Max Vonng
PostgreSQL 13.51 1 8 33.3 8C / 64G z1d.2xlarge Vonng
PostgreSQL 133.35 10 8 33.7 8C / 64G z1d.2xlarge Vonng
TiDB 190 100 120 15.8 120C / 570G TiDB
Spark 388 100 120 7.7 120C / 570G TiDB
Greenplum 436 100 288 2.9 120C / 570G TiDB
DeepGreen 148 200 256 19.0 288C / 1152G Digoal
MatrixDB 2306 1000 256 6.1 256C / 1024G MXDB
Hive 59599 1000 256 0.2 256C / 1024G MXDB
StoneDB 3388 100 64 1.7 64C / 128G StoneDB
ClickHouse 11537 100 64 0.5 64C / 128G StoneDB
OceanBase 189 100 96 19.8 96C / 384G OceanBase
PolarDB 387 50 32 14.5 32C / 128G 阿里云
PolarDB 755 50 16 14.9 16C / 64G 阿里云

为了便于衡量,我们可以归一化核数与仓数,用 QPH ,即每小时,每核,执行1仓 TPC-H 查询可以执行多少轮,来近似评估数据库的相对分析性能。

pg-performence-12.png

QPH = (1 / 时长) * (仓数 / 核数) * 3600

22个查询耗时对于不同仓数来说并非完全线性关系,因此只可作为近似参考。

不过总体来说,即使是 10 核的笔记本跑 PostgreSQL,也可以有相当亮眼的分析成绩来

(注:50C以上已经超过内存,走SWAP与磁盘IO了)。

pg-performence-13.png

图:论文《how good is my HTAP system》提出的评测 HTAP系统能力的方法 —— 吞吐量前沿,在AP/TP二维平面上画出混合负载的吞吐量极值。

至少在百GB级的表上,PostgreSQL足以称得上是一款表现优秀的分析数据库。如果单表超过几TB量级,也可以平滑升级至 Greenplum / MatrixDB / DeepGreen 等 PostgreSQL 兼容MPP数仓。。采用主从复制的 PostgreSQL 可以通过级联从库的方式近乎无限地 Scale 读负载,采用逻辑复制的 PostgreSQL 可以内置/同步地完成AP模式ETL,可谓是真正的 HTAP 数据库。

综上所述,PostgreSQL 在 TP 领域表现极其亮眼,在 AP 领域表现可圈可点。这也难怪在最近几年的 StackOverflow 开发者年度调研中, PostgreSQL 成为了 专业开发者最常用,最受喜爱,最想要的三冠王数据库

pg-performence-14.png

StackOverflow 近六年数据库开发者调研结果


参考

[1] Vonng: PGTPC

[2] WHY MYSQL

[3] MySQL Performance : 1M IO-bound QPS with 8.0 GA on Intel Optane SSD !

[4] MySQL Performance : 8.0 and Sysbench OLTP_RW / Update-NoKEY

[5] MySQL Performance : The New InnoDB Double Write Buffer in Action

[6] TiDB Sysbench Performance Test Report – v6.1.0 vs. v6.0.0

[7] OceanBase 3.1 Sysbench 性能测试报告

[8] Cockroach 22.15 Benchmarking Overview

[9] Benchmark YSQL performance using sysbench (v2.15)

[10] PolarDB-X 1.0 Sysbench 测试说明

[11] StoneDB OLAP TCP-H测试报告

[12] Elena Milkai: “How Good is My HTAP System?",SIGMOD ’22 Session 25

[13] AWS Calculator

为什么PostgreSQL是最成功的数据库?

微信公众号原文

当我们说一个数据库"成功"时,到底在说什么?是指功能性能易用性,还是成本生态复杂度?评价指标有很多,但这件事最终还得由用户来定夺。

数据库的用户是开发者,而开发者的意愿、喜好、选择又如何?StackOverflow 连续六年,向来自180个国家的七万多开发者问了这三个问题。

总览这六年的调研结果,不难看出在2022年,PostgreSQL 已经同时在这三项上登顶夺冠,成了字面意义上 “最成功的数据库”:

  • PostgreSQL 成为 专业开发者最常使用的数据库!(Used)
  • PostgreSQL 成为 开发者最为喜爱的数据库!(Loved)
  • PostgreSQL 成为开发者最想要用的数据库!(Wanted)

流行度反映当年势能,需求度预示来年动能,喜爱度代表长期潜能。时与势都站在 PostgreSQL 一侧,让我们来看一看更具体的数据与结果。


最流行

PostgreSQL —— 专业开发者中最流行的数据库!(Used)

第一项调研,是关于开发者目前使用着什么样的数据库,即,流行度

过去几年,MySQL一直霸占着数据库流行榜的榜首,很符合其 ”世界上最流行的开源关系型数据库“ 这一口号。不过这一次,”最流行“的桂冠恐怕要让给 PostgreSQL 了。

专业开发者中,PostgreSQL 以 46.5% 的使用率第一次超过 MySQL 位居第一,而 MySQL 以 45.7% 的使用率降至第二名。 同为泛用性最好的开源关系型数据库,排名第一第二的 PGSQL 与 MySQL ,与其他的数据库远远拉开了距离。

TOP 9 数据库流行度演变(2017-2022)

PGSQL 与 MySQL 的流行度差别并不大。值得一提的是,在见习开发者群体中,MySQL 仍然占据显著使用率优势(58.4%),如果算上见习开发者,MySQL 甚至仍然保有 3.3% 的微弱整体领先优势。

但从下图中不难看出,PostgreSQL 有显著的增长动能,而其他数据库,特别是 MySQL、 SQL Server、Oracle 的使用率则在最近几年持续衰退。随着时间的推移,PostgreSQL 的领先优势将进一步拉大。

四大关系型数据库流行度对比

流行度反映的是当下数据库的规模势能,而喜爱度反映的是未来数据库的增长潜能。


最喜爱

PostgreSQL —— 开发者最为喜爱的数据库!(Loved)

第二个问题是关于开发者喜爱什么数据库,讨厌什么数据库。在此项调研中,PostgreSQL与Redis一骑绝尘,以70%+ 的喜爱率高居榜首,显著甩开其他数据库。

在过去几年,Redis一直是用户最喜欢的数据库。在 2022 年,形势发生了变化,PostgreSQL 第一次超过 Redis,成为最受开发者喜爱的数据库。 Redis是简单易用的数据结构缓存服务器,经常会与关系型数据库搭配使用,广受开发者喜爱。不过开发者明显更爱功能强大得多的 PostgreSQL 多一丢丢。

相比之下 MySQL 与 Oracle 的表现就比较拉胯了。喜欢和讨厌 MySQL 的人基本各占一半;而只有35%的用户喜欢 Oracle ,这也意味着近 2/3 的开发者反感 Oracle 。

TOP 9 数据库喜爱度演变(2017-2022)

从逻辑上讲,用户的喜爱将导致软件的流行,用户的厌恶将导致软件过气。 我们可以参照 净推荐指数(NPS,又称口碑,推荐者%-贬损者%)的构造方式, 设计一个净喜爱指数 NLS:即 喜爱人群% - 厌恶人群%, 而数据库流行度的导数应当与 NLS 呈现正相关性 。

数据很好的印证了这一点: PGSQL 有着全场最高的 NLS: 44% ,对应着最高的流行度增长率 每年 460个基点。 MySQL 的口碑刚好落在褒贬线上方 (2.3%),流行度平均增速为36个基点; 而 Oracle 的口碑则为负的 29%,对应平均每年44个基点的使用率负增长。 当然在这份榜单上, Oracle 只是倒数第三惨的,最不受人待见的是 IBM DB2 : 1/4的人喜欢,3/4的人讨厌,NLS = -48% ,对应46个基点的年平均衰退。

当然,并不是所有潜能,都可以转换为实打实的动能。 用户的喜爱并不一定会付诸行动,而这就是第三项调研所要回答的问题。


最想要

PostgreSQL —— 开发者 最想使用的数据库!(Wanted)

“在过去的一年中,你在哪些数据库环境中进行了大量开发工作?在未来一年,你想在哪些数据库环境中工作? ”

对于这个问题前半段的回答,引出了”最流行“数据库的调研结果;而后半段,则给出了”最想要“这个问题的答案。 如果说用户的喜爱代表的是未来增长的潜能,那么用户的需求(想要,Want)就代表了下一年实打实的增长动能。

在今年的调研中, PostgreSQL 毫不客气的挤开 MongoDB ,占据了开发者最想使用数据库的宝座。 高达 19% 的受访者表示,下一年中想要使用 PostgreSQL 环境进行开发。 紧随其后的是 MongoDB (17%) 与 Redis (14%),这三种数据库的需求程度与其他数据库显著拉开了一个台阶。

此前, MongoDB 一直占据”最想要“数据库榜首,但最近开始出现过气乏力的态势。 原因是多方面的:例如,MongoDB 本身也受到了 PostgreSQL 的冲击。 PostgreSQL 本身就包含了完整的 JSON 特性,可直接用作文档数据库,更有类似 FerretDB (原名 MangoDB)的项目可以直接在 PG 上对外提供 MongoDB 的 API。

MongoDB 与 Redis 都是 NoSQL 运动的主力军。但与 MongoDB 不同,Redis的需求在不断增长。PostgreSQL 与 Redis,分别作为 SQL 与 NoSQL 的领军者,保持着旺盛的需求与高速的增长,前途无量。


为什么?

PostgreSQL 在需求率, 使用率,喜爱率上都拔得头筹,天时地利人和齐备,动能势能潜能都有,足以称得起是最成功的数据库了。

但我们想知道的是,为什么 PostgreSQL 会如此成功 ?

其实,秘密就藏在它的 Slogan 里: ”世界上最先进开源 关系型数据库“。


关系型数据库

关系型数据库是如此的普及与重要,也许其他的数据库品类如键值,文档,搜索引擎,时序,图,向量加起来也比不上它的一个零头。以至于当大家谈起数据库时,如果没有特殊说明,默认隐指的就是”关系型数据库“。在它面前,没有其他数据库品类敢称自己为”主流“。

DB-Engine 为例,DB-Engine的排名标准包括搜索系统名称时的搜索引擎结果数,Google趋势,Stack Overflow讨论,Indeed 提及系统的工作机会,LinkedIn等专业网络中的个人资料数,Twitter等社交网络中的提及数等,可理解为数据库的“综合热度”。

数据库热度趋势:https://db-engines.com/en/ranking_trend

在 DB-Engine 的热度趋势图中我们可以看到一条鸿沟,前四名全都是 关系型数据库 ,加上排名第五的 MongoDB,与其他数据库在热度上拉开了 数量级上的差距。 我们只需要把关注点聚焦到这四种核心的关系型数据库 Oracle,MySQL,SQL Server,PostgreSQL 上即可。

关系型数据库的生态位高度重叠,其关系可以视作零和博弈。抛开微软生态关门自嗨相对独立的商业数据库 SQL Server不提。在关系型数据库世界里,上演的是一场三国演义。

Oracle有才无德,MySQL才浅德薄,唯有PostgreSQL德才兼备。

Oracle是老牌商业数据库,有着深厚的历史技术积淀,功能丰富,支持完善。稳坐数据库头把交椅,广受不差钱且需要背锅侠的企业喜爱。但Oracle费用昂贵,且以讼棍行径成为知名的业界毒瘤。Microsoft SQL Server性质与Oracle类似,都属于商业数据库。商业数据库整体受开源数据库冲击,处于缓慢衰退的状态。

MySQL流行度位居第二,但树大招风,处于前狼后虎,上有野爹下有逆子的不利境地:在严谨的事务处理和数据分析上,MySQL被同为开源生态位的PostgreSQL甩开几条街;而在糙猛快的敏捷方法论上,MySQL又不如新兴NoSQL好用;同时 MySQL 上有养父 Oracle 压制,中有兄弟 MariaDB 分家,下有诸如逆子 TiDB 等协议兼容NewSQL分羹,因此也在走下坡路。

作为老牌商业数据库,Oracle的毋庸质疑,但其作为业界毒瘤,“” ,亦不必多说,故曰:“有才无德”。MySQL 虽有开源之功德,奈何认贼作父;且才疏学浅,功能简陋,只能干干CRUD,故曰“才浅德薄”。唯有PostgreSQL,德才兼备,既占据了开源崛起之天时,又把握住功能先进之地利,还有着宽松BSD协议之人和。正所谓:藏器于身,因时而动。不鸣则已,一鸣惊人,一举夺冠!

而 PostgreSQL 德以致胜的秘密,就是 先进开源


开源之德

PG的“德”在于开源。祖师爷级的开源项目,全世界开发者群策群力的伟大成果。

协议友善BSD,生态繁荣扩展多。开枝散叶,子孙满堂,Oracle替代扛旗者

什么叫“德”,合乎于“道”的表现就是德。而这条“道”就是开源

PostgreSQL是历史悠久的祖师爷级开源项目,更是全世界开发者群策群力的典范成果。

生态繁荣,扩展丰富,开枝散叶,子孙满堂

很久很久以前,开发软件/信息服务需要使用非常昂贵的商业数据库软件:例如Oracle与SQL Server:单花在软件授权上的费用可能就有六七位数,加之相近的硬件成本与服务订阅成本。Oracle一个 CPU 核一年的软件授权费用便高达十几万,即使壕如阿里也吃不消要去IOE。以 PostgreSQL / MySQL 为代表的的开源数据库崛起,让用户有了一个新选择:软件不要钱。“不要钱” 的开源数据库可以让我们自由随意地使用数据库软件,而这一点深刻影响了行业的发展:从接近一万¥/ 核·月的商业数据库,到20块钱/核·月的纯硬件成本。数据库走入寻常企业中,让免费提供信息服务成为可能。

开源是有大功的。互联网的历史就是开源软件的历史,IT行业之所以有今天的繁荣,人们能享受到如此多的免费信息服务,核心原因之一就是开源软件。开源是一种真正成功的,以软件自由为目的,由开发者构成的 Communism(社区主义):软件这种IT业的核心生产资料变为全世界开发者公有,按需分配。开发者各尽所能,人人为我,我为人人。

一个开源程序员工作时,其劳动背后可能蕴含的是数以万计顶尖开发者的智慧结晶。程序员薪资高从原理上来说是因为,开发者本质上不是一个简单的工人,而是一个指挥软件和硬件干活的包工头。程序员自己就是核心生产资料;软件来自公有社区;服务器硬件更是唾手可得;因此一个或几个高级的软件工程师,就可以很轻松的利用开源生态快速解决领域问题。

通过开源,所有社区开发者形成合力,极大降低了重复造轮子的内耗。使得整个行业的技术水平以匪夷所思的速度向前迈进。开源的势头就像滚雪球,时至今日已经势不可挡。基本上除了一些特殊场景和路径依赖,软件开发中闭门造车搞自力更生几乎成了一个大笑话。

越是底层基础的软件,开源便越占优势。开源,也是 PostgreSQL 对阵 Oracle 的最大底气所在。

Oracle 先进,但 PostgreSQL 也不差。PostgreSQL 是 Oracle 兼容性最好的开源数据库,原生即支持 Oracle 85% 的功能,更有 96% 功能兼容的专业发行版。但更重要的是,Oracle价格高昂,而PG开源免费。压倒性的成本优势让PG拥有了巨大的生态位基础:它不一定要在功能先进性上超过 Oracle 才能成功 ,廉价9成正确已经足以干翻 Oracle 。

PostgreSQL 可以视作一个开源版的“Oracle”,是唯一能真正威胁到 Oracle 的数据库。作为 ”去O“ 抗旗者,PG 可谓子孙满堂, 36% 的 “国产数据库” 更是直接基于PG “开发”,养活了一大批 自主可控 的 数据库公司,可谓功德无量。更重要的是,PostgreSQL 社区并不反对这样的行为,BSD 协议允许这样做。这样开放的胸襟,是被Oracle收购的,使用GPL协议的MySQL所难以相比的。


先进之才

PG的“才”在于先进。一专多长的全栈数据库,一个打十个,天生就是 HTAP。

时空地理分布式,时序文档超融合,单一组件即可覆盖几乎所有数据库需求。

PG的“才”在于一专多长。PostgreSQL是一专多长的全栈数据库,天生就是HTAP,超融合数据库,一个打十个。基本单一组件便足以覆盖中小型企业绝大多数的数据库需求:OLTP,OLAP,时序数据库,空间GIS,全文检索,JSON/XML,图数据库,缓存,等等等等。

PostgreSQL是各种关系型数据库中性价比最高的选择:它不仅可以用来做传统的CRUD OLTP业务,数据分析更是它的拿手好戏。各种特色功能更是提供了切入多种行业以的契机:基于PostGIS的地理时空数据处理分析,基于Timescale的时序金融物联网数据处理分析,基于Pipeline存储过程触发器的流式处理,基于倒排索引全文检索的搜索引擎,FDW对接统一各式各样的外部数据源。可以说,PG是真正一专多长的全栈数据库,它可以实现的比单纯OLTP数据库要丰富得多的功能。

在一个很可观的规模内,PostgreSQL都可以独立扮演多面手的角色,一个组件当多种组件使。而单一数据组件选型可以极大地削减项目额外复杂度,这意味着能节省很多成本。它让十个人才能搞定的事,变成一个人就能搞定的事。 不是说PG要一个打十个把其他数据库的饭碗都掀翻:专业组件在专业领域的实力是毋庸置疑的。但切莫忘记,为了不需要的规模而设计是白费功夫,这属于过早优化的一种形式。如果真有那么一样技术可以满足你所有的需求,那么使用该技术就是最佳选择,而不是试图用多个组件来重新实现它。

以探探为例,在 250w TPS与 200TB 数据的量级下,单一PostgreSQL选型依然能稳定可靠地撑起业务。能在很可观的规模内做到一专多长,除了本职的OLTP,PG 还在相当长的时间里兼任了缓存,OLAP,批处理,甚至消息队列的角色。当然神龟虽寿,犹有竟时。最终这些兼职功能还是要逐渐分拆出去由专用组件负责,但那已经是近千万日活时的事了。

vs MySQL

PostgreSQL 的先进性有目共睹,这也是其对阵同为开源关系型数据库的老对手 —— MySQL 时,真正的核心竞争力。

MySQL的口号是“世界上最流行的开源关系型数据库”,它的核心特点是糙猛快,用户基本盘是互联网。互联网公司的典型特点是什么?追逐潮流糙猛快说的是互联网公司业务场景简单(CRUD居多);数据重要性不高,不像传统行业(例如银行)那样在意数据的一致性与正确性;可用性优先,相比停服务更能容忍数据丢乱错,而一些传统行业宁可停止服务也不能让账目出错。 说的则是互联网行业数据量大,它们需要的就是水泥槽罐车做海量CRUD,而不是高铁和载人飞船。 说的则是互联网行业需求变化多端,出活周期短,要求响应时间快,大量需求的就是开箱即用的软件全家桶(如LAMP)和简单培训就能上手干活的CRUD Boy。于是,糙猛快的互联网公司和糙猛快的MySQL一拍即合。

但时过境迁,PostgreSQL 进步神速,在”快“与”猛“上 MySQL 已经不占优了,现在能拿出手的只剩下”糙“了。举个例子,MySQL 的哲学可以称之为:“好死不如赖活着”,与 “我死后哪管洪水滔天”。 其“糙”体现在各种“容错”上,例如允许呆瓜程序员写出的错误的SQL也能跑起来。最离谱的例子就是MySQL竟然允许部分成功的事务提交,这就违背了关系型数据库的基本约束:原子性与数据一致性

图:MySQL默认竟然允许部分成功的事务提交

先进的因会反映为流行的果,流行的东西因为落后而过气,而先进的东西会因为先进变得流行。时代所赋予的红利,也会随时代过去而退潮。在这个变革的时代中,没有先进的功能打底,“流行”也也难以长久。在先进性上, PostgreSQL 丰富的功能已经甩开 MySQL 了几条街,而 MySQL 引以为豪的 ”流行度“ 也开始被 PostgreSQL 反超。

大势所趋,大局已定。正所谓:时来天地皆同力,运去英雄不自由。先进与开源,就是 PostgreSQL 最大的两样杀手锏。Oracle 先进, MySQL 开源,PostgreSQL 先进又开源。天时地利人和齐备,何愁大业不成?


展望未来

软件吞噬世界, 开源吞噬软件,而云吞噬开源。

看上去,数据库之争已经尘埃落定,一段时间内大概不会有其他数据库内核能威胁到 PostgreSQL 了。 但对 PostgreSQL 开源社区 真正的威胁,已经不再是其他数据库内核,而是软件使用范式的嬗变:云出现了。

最初,大家开发软件/信息服务需要使用昂贵的商业软件( Oracle,SQL Server,Unix)。而随着 Linux / PostgreSQL 这些开源软件的兴起,用户们有了新的选择。开源软件确实免费不要钱,但想用好开源软件,是一件门槛很高的事情,用户不得不雇佣开源软件专家来帮助自己用好开源软件。

当数据库上了规模,雇佣开源DBA自建始终是合算的,只是好DBA太稀缺了。

这便是开源的核心模式:开源软件开发者给开源软件做贡献;开源软件通过好用免费吸引大量用户;用户在使用开源软件时产生需求,创造更多开源软件相关就业岗位,创造更多的开源软件开发者。 这三步形成了一个正反馈循环:更多的开源贡献者让开源软件更好用,更省钱,从而吸引更多用户,并创造出更多的开源贡献者。开源生态的繁荣有赖于这个闭环,而公有云厂商的出现打破了这个循环。

公有云厂商将开源数据库套上壳,加上自己的硬件与管控软件,雇佣共享DBA提供支持,便成了云数据库。诚然这是一项很有价值的服务,但云厂商将开源软件放在自家的云平台售卖而鲜有回馈,实质上是一种通过“搭便车”吸血开源的行为。 这样的共享外包模式将导致开源软件的岗位向云厂商集中,最终形成少数巨头做大垄断,伤害到所有用户的软件自由。

世界已经被云改变了,闭源软件早已不是最重要的问题了。

在 2020 年,计算自由的敌人是云计算软件”。

这是 DDIA 作者 Martin Kleppmann 在其“本地优先软件”运动中提出的 宣言。云软件指的是运行在供应商服务器上的软件,例如:Google Docs、Trello、Slack、Figma、Notion 。以及最核心的云软件,云数据库

后云时代,开源社区如何应对云软件的挑战?Cloud Native 运动给出了答案。这是一场从公有云夺回软件自由的伟大运动,而数据库,则是其中的核心焦点。

Cloud Native 全景图,还缺少最后一块拼图:有状态的数据库!

这也是我们做 开箱即用的开源PostgreSQL 数据库发行版 —— Pigsty 想要解决的问题:做一个用户在本地即可使用的RDS服务,成为云数据库的开源替代!

Pigsty 带有开箱即用的 RDS / PaaS / SaaS 整合;一个无可比拟的PG监控系统与自动驾驶的高可用集群架构方案;一键安装部署,并提供 Database as Code 的易用体验;在体验比肩甚至超越云数据库的前提下,数据自主可控且成本减少 50% ~ 90%。我们希望它能极大降低 PostgreSQL 使用的门槛,让更多用户可以用 好数据库用好 数据库。

当然,限于篇幅,云数据库与后云时代的数据库未来,就是下一篇文章要介绍的故事了。

开箱即用的PG发行版:Pigsty

微信公众号原文


什么是Pigsty

Pigsty是开箱即用的生产级开源PostgreSQL发行版

所谓发行版(Distribution),指的是由数据库内核及其一组软件包组成的数据库整体解决方案。例如,Linux是一个操作系统内核,而RedHat,Debian,SUSE则是基于此内核的操作系统发行版。PostgreSQL是一个数据库内核,而Pigsty,BigSQL,Percona,各种云RDS,换皮数据库则是基于此内核的数据库发行版

Pigsty区别于其他数据库发行版的五个核心特性为:

  • 全面专业监控系统
  • 稳定可靠部署方案
  • 简单省心的用户界面
  • 灵活开放扩展机制
  • 免费友好开源协议

这五个特性,使得Pigsty真正成为开箱即用的PostgreSQL发行版。

谁会感兴趣?

Pigsty面向的用户群体包括:DBA,架构师,OPS,软件厂商、云厂商、业务研发、内核研发、数据研发;对数据分析与数据可视化感兴趣的人;学生,新手程序员,有兴趣尝试数据库的用户。

对于DBA,架构师等专业用户,Pigsty提供了独一无二的专业级PostgreSQL监控系统,为数据库管理提供不可替代的价值点。与此同时,Pigsty还带有一个稳定可靠,久经考验的生产级PostgreSQL部署方案,可在生产环境中自动部署带有监控报警,日志采集,服务发现,连接池,负载均衡,VIP,以及高可用的PostgreSQL数据库集群。

对于研发人员(业务研发、内核研发、数据研发),学生,新手程序员,有兴趣尝试数据库的用户,Pigsty提供了门槛极低,一键拉起,一键安装本地沙箱。本地沙箱除机器规格外与生产环境完全一致,包含完整的功能:带有开箱即用的数据库实例与监控系统。可用于学习,开发,测试,数据分析等场景。

此外,Pigsty提供了一种称为“Datalet”的灵活扩展机制 。对数据分析与数据可视化感兴趣的人可能会惊讶地发现,Pigsty还可以作为数据分析与可视化的集成开发环境。Pigsty集成了PostgreSQL与常用的数据分析插件,并带有Grafana和内嵌的Echarts支持,允许用户编写,测试,分发数据小应用(Datalet)。如:“Pigsty监控系统的额外扩展面板包”,“Redis监控系统”,“PG日志分析系统”,“应用监控”,“数据目录浏览器”等。

最后,Pigsty采用了免费友好的Apache License 2.0,可以免费用于商业目的。只要遵守Apache 2 License的显著声明条款,也欢迎云厂商与软件厂商集成与二次研发商用


全面专业的监控系统

You can’t manage what you don’t measure.

— Peter F.Drucker

Pigsty提供专业级监控系统,面向专业用户提供不可替代的价值点。

以医疗器械类比,普通监控系统类似于心率计、血氧计,普通人无需学习也可以上手。它可以给出患者生命体征核心指标:起码用户可以知道人是不是要死了,但对于看病治病无能为力。例如,各种云厂商软件厂商提供的监控系统大抵属于此类:十几个核心指标,告诉你数据库是不是还活着,让人大致有个数,仅此而已。

专业级监控系统则类似于CT,核磁共振仪,可以检测出对象内部的全部细节,专业的医师可以根据CT/MRI报告快速定位疾病与隐患:有病治病,没病健体。Pigsty可以深入审视每一个数据库中的每一张表,每一个索引,每一个查询,提供巨细无遗的全面指标(1155类),并通过几千个仪表盘将其转换为洞察:将故障扼杀在萌芽状态,并为性能优化提供实时反馈

Pigsty监控系统基于业内最佳实践,采用Prometheus、Grafana作为监控基础设施。开源开放,定制便利,可复用,可移植,没有厂商锁定。可与各类已有数据库实例集成。


稳定可靠的部署方案

A complex system that works is invariably found to have evolved from a simple system that works.

—John Gall, Systemantics (1975)

数据库是管理数据的软件,管控系统是管理数据库的软件。

Pigsty内置了一套以Ansible为核心的数据库管控方案。并基于此封装了命令行工具与图形界面。它集成了数据库管理中的核心功能:包括数据库集群的创建,销毁,扩缩容;用户、数据库、服务的创建等。Pigsty采纳“Infra as Code”的设计哲学使用了声明式配置,通过大量可选的配置选项对数据库与运行环境进行描述与定制,并通过幂等的预置剧本自动创建所需的数据库集群,提供近似私有云般的使用体验。

Pigsty创建的数据库集群是分布式高可用的数据库集群。Pigsty创建的数据库基于DCS、Patroni、Haproxy实现了高可用。数据库集群中的每个数据库实例在使用上都是幂等的,任意实例都可以通过内建负载均衡组件提供完整的读写服务,提供分布式数据库的使用体验。数据库集群可以自动进行故障检测与主从切换,普通故障能在几秒到几十秒内自愈,且期间只读流量不受影响。故障时。集群中只要有任意实例存活,就可以对外提供完整的服务。

Pigsty的架构方案经过审慎的设计与评估,着眼于以最小复杂度实现所需功能。该方案经过长时间,大规模的生产环境验证,已经被互联网/B/G/M/F多个行业内的组织所使用。


简单省心的用户界面

Pigsty旨在降低PostgreSQL的使用门槛,因此在易用性上做了大量工作。

安装部署

Someone told me that each equation I included in the book would halve the sales.

— Stephen Hawking

Pigsty的部署分为三步:下载源码,配置环境,执行安装,均可通过一行命令完成。遵循经典的软件安装模式,并提供了配置向导。您需要准备的只是一台CentOS7.8机器及其root权限。管理新节点时,Pigsty基于Ansible通过ssh发起管理,无需安装Agent,即使是新手也可以轻松完成部署。

Pigsty既可以在生产环境中管理成百上千个高规格的生产节点,也可以独立运行于本地1核1GB虚拟机中,作为开箱即用的数据库实例使用。在本地计算机上使用时,Pigsty提供基于Vagrant与Virtualbox的沙箱。可以一键拉起与生产环境一致的数据库环境,用于学习,开发,测试数据分析,数据可视化等场景。

用户接口

Clearly, we must break away from the sequential and not limit the computers. We must state definitions and provide for priorities and descriptions of data. We must state relation‐ ships, not procedures.

—Grace Murray Hopper, Management and the Computer of the Future (1962)

Pigsty吸纳了Kubernetes架构设计中的精髓,采用声明式的配置方式与幂等的操作剧本。用户只需要描述“自己想要什么样的数据库”,而无需关心Pigsty如何去创建它,修改它。Pigsty会根据用户的配置文件清单,在几分钟内从裸机节点上创造出所需的数据库集群。

在管理与使用上,Pigsty提供了不同层次的用户界面,以满足不同用户的需求。新手用户可以使用一键拉起的本地沙箱与图形用户界面,而开发者则可以选择使用pigsty-cli命令行工具与配置文件的方式进行管理。经验丰富的DBA、运维与架构师则可以直接通过Ansible原语对执行的任务进行精细控制。

灵活开放的扩展机制

PostgreSQL的 可扩展性(Extensible) 一直为人所称道,各种各样的扩展插件让PostgreSQL成为了最先进的开源关系型数据库。Pigsty亦尊重这一价值,提供了一种名为“Datalet”的扩展机制,允许用户和开发者对Pigsty进行进一步的定制,将其用到“意想不到”的地方,例如:数据分析与可视化。

当我们拥有监控系统与管控方案后,也就拥有了开箱即用的可视化平台Grafana与功能强大的数据库PostgreSQL。这样的组合拥有强大的威力 —— 特别是对于数据密集型应用而言。用户可以在无需编写前后端代码的情况下,进行数据分析与数据可视化,制作带有丰富交互的数据应用原型,甚至应用本身。

Pigsty集成了Echarts,以及常用地图底图等,可以方便地实现高级可视化需求。比起Julia,Matlab,R这样的传统科学计算语言/绘图库而言,PG + Grafana + Echarts的组合允许您以极低的成本制作出可分享可交付标准化的数据应用或可视化作品。

Pigsty监控系统本身就是Datalet的典范:所有Pigsty高级专题监控面板都会以Datalet的方式发布。Pigsty也自带了一些有趣的Datalet案例:Redis监控系统,新冠疫情数据分析,七普人口数据分析,PG日志挖掘等。后续还会添加更多的开箱即用的Datalet,不断扩充Pigsty的功能与应用场景。


免费友好的开源协议

Once open source gets good enough, competing with it would be insane.

Larry Ellison —— Oracle CEO

在软件行业,开源是一种大趋势,互联网的历史就是开源软件的历史,IT行业之所以有今天的繁荣,人们能享受到如此多的免费信息服务,核心原因之一就是开源软件。开源是一种真正成功的,由开发者构成的communism(译成社区主义会更贴切):软件这种IT业的核心生产资料变为全世界开发者公有,人人为我,我为人人。

一个开源程序员工作时,其劳动背后其实可能蕴含有数以万计的顶尖开发者的智慧结晶。通过开源,所有社区开发者形成合力,极大降低了重复造轮子的内耗。使得整个行业的技术水平以匪夷所思的速度向前迈进。开源的势头就像滚雪球,时至今日已经势不可挡。除了一些特殊场景和路径依赖,软件开发中闭门造车搞自力更生已经成了一个大笑话。

依托开源,回馈开源。Pigsty采用了友好的Apache License 2.0,可以免费用于商业目的只要遵守Apache 2 License的显著声明条款,也欢迎云厂商与软件厂商集成与二次研发商用


关于Pigsty

A system cannot be successful if it is too strongly influenced by a single person. Once the initial design is complete and fairly robust, the real test begins as people with many different viewpoints undertake their own experiments. — Donald Knuth

Pigsty围绕开源数据库PostgreSQL而构建,PostgreSQL是世界上最先进的开源关系型数据库,而Pigsty的目标就是:做最好用的开源PostgreSQL发行版

在最开始时,Pigsty并没有这么宏大的目标。因为在市面上找不到任何满足我自己需求的监控系统,因此我只好自己动手,丰衣足食,给自己做了一个监控系统。没有想到它的效果出乎意料的好,有不少外部组织PG用户希望能用上。紧接着,监控系统的部署与交付成了一个问题,于是又将数据库部署管控的部分加了进去;在生产环境应用后,研发希望能在本地也有用于测试的沙箱环境,于是又有了本地沙箱;有用户反馈ansible不太好用,于是就有了封装命令的pigsty-cli命令行工具;有用户希望可以通过UI编辑配置文件,于是就有了Pigsty GUI。就这样,需求越来越多,功能也越来越丰富,Pigsty也在长时间的打磨中变得更加完善,已经远远超出了最初的预期。

做这件事本身也是一种挑战,做一个发行版有点类似于做一个RedHat,做一个SUSE,做一个“RDS产品”。通常只有一定规模的专业公司与团队才会去尝试。但我就是想试试,一个人可不可以?实际上除了慢一点,也没什么不可以。一个人在产品经理、开发者,终端用户的角色之间转换是很有趣的体验,而“Eat dog food”最大的好处就是,你自己既是开发者也是用户,你了解自己需要什么,也不会在自己的需求上偷懒。

不过,正如高德纳所说:“带有太强个人色彩的系统无法成功”。 要想让Pigsty成为一个具有旺盛生命力的项目,就必须开源,让更多的人用起来。“当最初的设计完成并足够稳定后,各式各样的用户以自己的方式去使用它时,真正的挑战才刚刚开始”。

Pigsty很好的解决了我自己的问题与需求,现在我希望它可以帮助到更多的人,并让PostgreSQL的生态更加繁荣,更加多彩。

为什么PostgreSQL前途无量?

微信公众号原文

最近做的事儿都围绕着PostgreSQL生态,因为我一直觉得这是一个前途无量的方向。

为什么这么说?因为数据库是信息系统的核心组件,关系型数据库是数据库中的绝对主力,而PostgreSQL是世界上最先进的开源关系型数据库。占据天时地利,何愁大业不成?

做一件事最重要的就是认清形势,时来天地皆同力,运去英雄不自由。


天下大势

今天下三分,然Oracle | MySQL | SQL Server 疲敝,日薄西山。PostgreSQL紧随其后,如日中天。前四的数据库中,前三者都在走下坡路,唯有PG增长势头不减,此消彼长,前途无量。

DB-Engine 数据库流行度趋势 (注意这是对数坐标系)

在唯二两个头部开源关系型数据库 MySQL & PgSQL 中,MySQL (2nd) 虽占上风,但其生态位却在逐渐被PostgreSQL (4th) 和非关系型的文档数据库MongoDB (5th) 抢占。按照现在的势头,几年后PostgreSQL的流行度即将跻身前三,与Oracle、MySQL分庭抗礼。


竞争关系

关系型数据库的生态位高度重叠,其关系可以视作零和博弈。与PostgreSQL形成直接竞争关系的,就是OracleMySQL

Oracle流行度位居第一,是老牌商业数据库,有着深厚的历史技术积淀,功能丰富,支持完善。稳坐数据库头把交椅,广受不差钱的企业组织喜爱。但Oracle费用昂贵,且以讼棍行径成为知名的业界毒瘤。排名第三的SQL Server属于相对独立的微软生态,性质上与Oracle类似,都属于商业数据库。商业数据库整体受开源数据库冲击,流行度处于缓慢衰减的状态。

MySQL流行度位居第二,但树大招风,处于前有狼后有虎,上有野爹下有逆子的不利境地:在严谨的事务处理和数据分析上,MySQL被同为开源关系型数据库的PgSQL甩开几条街;而在糙猛快的敏捷方法论上,MySQL又不如新兴NoSQL。同时,MySQL上有养父Oracle的压制,中有MariaDB分家,下有诸如TiDB,OB之类的兼容性新数据库分羹,因而也止步不前。

唯有PostgreSQL迎头赶上,保持着近乎指数增长的势头。如果说几年前PG的势还是Potential,那么现在Potential已经开始兑现为Impact,开始对竞品构成强力挑战。

而在这场你死我活的斗争中,PostgreSQL占据了三个“”:

  1. 开源软件普及发展,蚕食商业软件市场

    在去IOE与开源浪潮的大背景下,凭借开源生态对商业软件(Oracle)形成压制。

  2. 满足用户日益增长的数据处理功能需求

    凭借地理空间数据的事实标准PostGIS处理立于不败之地,凭借对标Oracle的极为丰富的功能,对MySQL形成技术压制。

  3. 市场份额均值回归的势

    国内PG市场份额因历史原因,远低于世界平均水平,本身蕴含着巨大势能。

Oracle作为老牌商业软件,毋庸质疑,同时作为业界毒瘤,“”也不必多说,故曰:“有才无德”。MySQL有开源之功德,但它一来采用了GPL协议,比起使用无私宽松BSD协议的PgSQL还是差不少意思,二来认贼作父,被Oracle收购,三来才疏学浅,功能简陋,故曰“才浅德薄”。

德不配位,必有灾殃。唯有PostgreSQL,既占据了开源崛起之天时,又把握住功能强劲之地利,还有着宽松BSD协议之人和。正所谓:藏器于身,因时而动。不鸣则已,一鸣惊人。德才兼备,攻守之势易矣!


德才兼备

PostgreSQL的德

PG的“德”在于开源。什么叫“德”,合乎于“道”的表现就是德。而这条“道”就是开源

PG本身就是祖师爷级开源软件,是开源世界中的一颗明珠,是全世界开发者群策群力的成功典范。而且更重要的是它采用无私的BSD协议:除了打着PG的名号招摇撞骗外,基本可以说是百无禁忌:比如换皮改造为国产数据库出售。PG可谓无数数据库厂商们的衣食父母。子孙满堂,活人无数,功德无量。

数据库谱系图,若列出所有PgSQL衍生版,估计可以撑爆这张图

PostgreSQL的才

PG的“才”在于一专多长。PostgreSQL是一专多长的全栈数据库,天生就是HTAP,超融合数据库,一个打十个。基本单一组件便足以覆盖中小型企业绝大多数的数据库需求:OLTP,OLAP,时序数据库,空间GIS,全文检索,JSON/XML,图数据库,缓存,等等等等。

PostgreSQL在一个很可观的规模内都可以独立扮演多面手的角色,一个组件当多种组件使。而单一数据组件选型可以极大地削减项目额外复杂度,这意味着能节省很多成本。它让十个人才能搞定的事,变成一个人就能搞定的事。 如果真有那么一样技术可以满足你所有的需求,那么使用该技术就是最佳选择,而不是试图用多个组件来重新实现它。

参考阅读:PG好处都有啥


开源之德

开源是有大功的。互联网的历史就是开源软件的历史,IT行业之所以有今天的繁荣,人们能享受到如此多的免费信息服务,核心原因之一就是开源软件。开源是一种真正成功的,由开发者构成的communism(译成社区主义会更贴切):软件这种IT业的核心生产资料变为全世界开发者公有,人人为我,我为人人。

一个开源程序员干活时,其劳动背后其实可能蕴含有数以万计的顶尖开发者的智慧结晶。互联网程序员贵,因为从效果上来讲,其实程序员不是一个工人,而是一个指挥软件和机器来干活的包工头。 程序员自己就是核心生产资料,服务器很容易取得(相比其他行业的科研设备与实验环境),软件来自公有社区,一个或几个高级的软件工程师可以很轻松的利用开源生态快速解决领域问题。

通过开源,所有社区开发者形成合力,极大降低了重复造轮子的内耗。使得整个行业的技术水平以匪夷所思的速度向前迈进。开源的势头就像滚雪球,时至今日已经势不可挡。基本上除了一些特殊场景和路径依赖,软件开发中闭门造车搞自力更生几乎成了一个大笑话。

所以说,搞数据库也好,做软件也罢,要搞技术就要搞开源的技术,闭源的东西生命力太弱,没意思。开源之德,也是PgSQL与MySQL对Oracle的最大底气所在。


生态之争

开源的核心就在于生态(ECO),每一个开源技术都有自己的小生态。所谓生态就是各种主体及其环境通过密集相互作用构成的一个系统,而开源软件的生态模式大致可以描述为由以下三个步骤组成的正反馈循环:

  • 开源软件开发者给开源软件做贡献
  • 开源软件本身免费,吸引更多用户
  • 用户使用开源软件,产生需求,创造更多开源软件相关岗位

开源生态的繁荣有赖于这个闭环,而生态系统的规模(用户/开发者数量)与复杂度(用户/开发者质量)直接决定了这个软件的生命力,所以每一个开源软件都有天命去扩大自己的规模。而软件的规模通常取决于软件所占据的生态位,如果不同的软件的生态位重叠,就会发生竞争。在开源关系型数据库的生态位中,PgSQL与MySQL就是最直接的竞争者。


流行 vs 先进

MySQL的口号是“世界上最流行的开源关系型数据库”,而PostgreSQL的Slogan则是“世界上最先进的开源关系型数据库”,一看这就是一对老冤家了。这两个口号很好的反映出了两种产品的特质:PostgreSQL是功能丰富,一致性优先,高大上的严谨的学院派数据库;MySQL是功能粗陋,可用性优先,糙猛快的“工程派”数据库。

MySQL的主要用户群体集中在互联网公司,互联网公司的典型特点是什么?追逐潮流糙猛快说的是互联网公司业务场景简单(CRUD居多);数据重要性不高,不像传统行业(例如银行)那样在意数据的一致性(正确性);可用性优先(相比停服务更能容忍数据丢乱错,而一些传统行业宁可停止服务也不能让账目出错)。 说的则是互联网行业数据量大,它们需要的就是水泥槽罐车,而不是高铁和载人飞船。 说的则是互联网行业需求变化多端,出活周期短,要求响应时间快,大量需求的就是开箱即用的软件全家桶(如LAMP)和简单培训一下就能干活的CRUD Boy。于是糙猛快的互联网公司和糙猛快的MySQL一拍即合。

而PgSQL的用户则更偏向于传统行业,传统行业之所以称为传统行业,就是因为它们已经走过了野蛮生长的阶段,有着成熟的业务模型与深厚的底蕴积淀。它们需要的是正确的结果,稳定的表现,丰富的功能,对数据进行分析加工提炼的能力。所以在传统行业中,往往是Oracle、SQL Server、PostgreSQL的天下。特别是在地理相关的场景中更是有着不可替代的地位。与此同时,不少互联网公司的业务也开始成熟沉淀,已经一只脚迈入“传统行业”了,越来越多的互联网公司脱离了糙猛快的低级循环,将目光投向PostgreSQL 。


谁更正确?

最了解一个人的的往往是他的竞争对手,PostgreSQL与MySQL的口号都很精准地戳中了对手的痛点。PgSQL“最先进”的潜台词就是MySQL太落后,而MySQL”最流行“就是说PgSQL不流行。用户少但先进,用户多但落后。哪一个更”好“?这种价值判断的问题不好回答。

但我认为时间站在 先进 技术的一边:因为先进与落后是技术的核心度量,是因,而流行与否则是果;流行不流行是内因(技术是否先进)和外因(历史路径依赖)共同对时间积分的结果。当下的因会反映为未来的果:流行的东西因为落后而过气,而先进的东西会因为先进变得流行。

虽然很多流行的东西都是垃圾,但流行并不一定代表着落后。如果只是缺少一些功能,MySQL还不至于被称为“落后”。问题在于MySQL已经糙到连事务这种关系型数据库的基本功能都有缺陷,那就不是落后不落后能概括的问题,而是合格不合格的问题了。

ACID

一些作者声称,支持通用的两阶段提交代价太大,会带来性能与可用性的问题。让程序员来处理过度使用事务导致的性能问题,总比缺少事务编程好得多。 ——James Corbett等,Spanner:Google的全球分布式数据库(2012)

在我看来, MySQL的哲学可以称之为:“好死不如赖活着”,以及,“我死后哪管洪水滔天”。 其“可用性”体现在各种“容错”上,例如允许呆瓜程序员写出的错误的SQL查询也能跑起来。最离谱的例子就是MySQL竟然允许部分成功的事务提交,这就违背了关系型数据库的基本约束:原子性与数据一致性

图:MySQL竟然允许部分成功的事务提交

这里在一个事务中插入了两条记录,第一条成功,第二条因为约束失败。根据事务的原子性,整个事务要么整个成功,要么整个失败(最终一条都没有插入)。结果MySQL的默认表现竟然是允许部分成功的事务提交,也就是事务没有原子性没有原子性就没有一致性,如果这个事务是一笔转账(先扣再加),因为某些原因失败,那这里的帐就做不平了。这种数据库如果用来记账恐怕是一笔糊涂账,所以说什么“金融级MySQL”恐怕就是一个笑话。

当然,滑稽的是还有一些MySQL用户将其称为“特性”,说这体现了MySQL的容错性。实际上,此类“特殊容错”需求在SQL标准中完全可以通过SAVEPOINT机制实现。PgSQL对此的实现就堪称典范,psql客户端允许通过ON_ERROR_ROLLBACK选项,隐式地在每条语句后创建SAVEPOINT,并在语句失败后自动ROLLBACK TO SAVEPOINT,以标准SQL的方式,以客户端可选项的形式,在不破坏事物ACID的情况下,同样实现这种看上去便利实则苟且的功能。相比之下,MySQL的这种所谓“特性”是以直接在服务端默认牺牲事务ACID为代价的(这意味着用户使用JDBC,psycopg等应用驱动也照样受此影响)。

如果是互联网业务,注册个新用户丢个头像、丢个评论可能不是什么大事。数据那么多,丢几条,错几条又算个什么?别说是数据,业务本身很可能都处于朝不保夕的状态,所以糙又如何?万一成功了,前人拉的屎反正也是后人来擦。所以一些互联网公司通常并不在乎这些。

PostgreSQL所谓“严格的约束与语法“可能对新人来说“不近人情”,例如,一批数据中如果有几条脏数据,MySQL可能会照单全收,而PG则会严格拒绝。尽管苟且妥协看上去很省事,但在其他地方卖下了雷:因为逻辑炸弹深夜加班排查擦屁股的工程师,和不得不天天清洗脏数据的数据分析师肯定对此有很大怨念。从长期看,要想成功,做正确的事最重要。

一个成功的技术,现实的优先级必须高于公关,你可以糊弄别人,但糊弄不了自然规律。

——罗杰斯委员会报告(1986)

MySQL的流行度并没有和PgSQL相差太远,然而其功能比起PostgreSQL和Oracle却是差距不小。Oracle与PostgreSQL算诞生于同一时期,再怎么斗,立场与阵营不同,也有点惺惺相惜的老对手的意思:都是扎实修炼了半个世纪内功,厚积薄发的老法师。而MySQL就像心浮气躁耍刀弄枪的二十来岁毛头小伙子,凭着一把蛮力,借着互联网野蛮生长的黄金二十年趁势而起,占山为王。

时代所赋予的红利,也会随时代过去而退潮。在这个变革的时代中,没有先进的功能打底,“流行”也恐怕也难以长久。


发展前景

从个人职业发展前景的角度看,很多数程序员学习一门技术的原因都是为了提高自己的技术竞争力(从而更好占坑赚钱)。PostgreSQL是各种关系型数据库中性价比最高的选择:它不仅可以用来做传统的CRUD OLTP业务,数据分析更是它的拿手好戏。各种特色功能更是提供了切入多种行业以的契机:基于PostGIS的地理时空数据处理分析,基于Timescale的时序金融物联网数据处理分析,基于Pipeline存储过程触发器的流式处理,基于倒排索引全文检索的搜索引擎,FDW对接统一各式各样的外部数据源。可以说,它是真正一专多长的全栈数据库,用它可以实现的功能要比单纯的OLTP数据库要丰富得多,更是为CRUD码农提供了转型和深入的进阶道路。

企业用户的角度来看,PostgreSQL在一个很可观的规模内都可以独立扮演多面手的角色,一个组件当多种组件使。而单一数据组件选型可以极大地削减项目额外复杂度,这意味着能节省很多成本。它让十个人才能搞定的事,变成一个人就能搞定的事。 当然这不是说PG要一个打十个把其他数据库的饭碗都掀翻,专业组件在专业领域的实力是毋庸置疑的。但切莫忘记,为了不需要的规模而设计是白费功夫,实际上这属于过早优化的一种形式。如果真有那么一样技术可以满足你所有的需求,那么使用该技术就是最佳选择,而不是试图用多个组件来重新实现它。

以探探为例,在250WTPS与200TB数据的量级下,单一PostgreSQL选型依然能稳如狗地支撑业务。能在很可观的规模内做到一专多长,除了本职的OLTP,Pg还在相当长的时间里兼任了缓存,OLAP,批处理,甚至消息队列的角色。当然神龟虽寿,犹有竟时。最终这些兼职功能还是要逐渐分拆出去由专用组件负责,但那已经是近千万日活时的事了。

商业生态的角度看,PostgreSQL也有巨大的优势。一来PG技术先进,可称为 “开源版Oracle”。原生的PG基本可以对Oracle的功能做到八九成兼容,EDB更是有96% Oracle兼容的专业PG发行版。因此在抢占去O腾退出的市场中,PostgreSQL及其衍生版本的技术优势是压倒性的。二来PG协议友善,采用了宽松的BSD协议。因此各种数据库厂商,云厂商出品的“自研数据库”,以及很多“云数据库”大体都是基于PgSQL改造的。例如最近HW基于PostgreSQL搞openGaussDB就是一个很明智的选择。不要误会,PG的协议确实允许这样做,而且这样做也确实让PostgreSQL的生态更加繁荣壮大。卖PostgreSQL衍生版是一个很成熟的市场:传统企业不差钱且愿意为此付费买单。开源天才之火有商业利益之油浇灌,因而源源不断地释放出旺盛的生命力。

vs MySQL

作为老对手,MySQL的处境就有些尴尬了。

从个人职业发展上来看,学MySQL主要就是干CRUD。学好增删改查成为一个合格的码农是没问题的,然而谁又愿意一直“数据矿工”的活呢?数据分析才是数据产业链上的暴利肥差。以MySQL孱弱的分析能力,很难支持CURD程序员升级转型发展。此外,PostgreSQL的市场需求摆在那里,但现在却面临供不应求的状况(以至于现在大量良莠不齐的PG培训机构如雨后春笋般冒了出来),MySQL的人确实比PgSQL的人好招,这是不假的。但反过来说MySQL界的内卷程度也要大的多,供不应求方才体现稀缺性,人太多了技能也就贬值了。

从企业用户的角度来看,MySQL就是专用于OLTP的单一功能组件,往往需要ES, Redis, Mongo等其他等等一起配合才能满足完整的数据存储需求,而PG基本就不会有这个问题。此外,MySQL和PgSQL都是开源数据库,都“免费”。免费的Oracle和免费的MySQL用户会选择哪个呢?

从商业生态来看,MySQL面临的最大问题是 叫好不叫座。叫好当然是因为越流行则声音越大,尤其主要的用户互联网企业本身就占据话语权高地。不叫座当然也是因为互联网公司本身对于这类软件付费的意愿是极弱的:怎么算都是养几个MySQL DBA直接用开源的更合算。此外,因为MySQL的GPL协议要求衍生软件也要开源,软件厂商基于MySQL研发的动机也不强,基本都是采用 兼容“MySQL” 协议来分MySQL的市场蛋糕,而不是基于MySQL的代码进行开发与回馈,让人对其生态健康程度产生怀疑。

当然MySQL最大的问题就在于:它的生态位越来越狭窄。论严谨的事务处理与数据分析,PostgreSQL甩开它几条街;论糙猛快,快速出原型,NoSQL全家桶又要比MySQL方便太多。论商业发财,上面有Oracle干爹压着;论开源生态,又不断出现MySQL兼容的新生代产品来尝试替代主体。可以说MySQL处在一种吃老本的位置上,只是凭籍历史积分存量维持着现状的地位。时间是否会站在MySQL这一边,我们拭目以待。

vs NewSQL

最近市场上当然也有一些很亮眼的NewSQL产品,例如TiDB,Cockroachdb,Yugabytedb等等。何如?我认为它们都是很好的产品,有一些不错的技术亮点,都是对开源技术的贡献。但是它们可能同样面临叫好不叫座的困局。

NewSQL的大体特征是:主打“分布式”的概念,通过“分布式”解决水平扩展性容灾高可用两个问题,并因分布式的内在局限性会牺牲许多功能,只能提供较为简单有限的查询支持。分布式数据库在高可用容灾方面与传统主从复制并没有质的区别,因此其特征主要可以概括为“以量换质”。

然而对很多企业而言,牺牲功能换取扩展性很可能是一个伪需求弱需求。在我接触过的为数不少的用户中,绝大多数场景下的的数据量和负载水平完全落在单机Postgres的处理范围内(目前弄过的记录是单库15TB,单集群40万TPS)。从数据量上来讲,绝大多数企业终其生命周期的数据量也超不过这个瓶颈;至于性能就更不重要了,过早优化是万恶之源,很多企业的DB性能余量足够让他们把所有业务逻辑用存储过程编写然后高高兴兴的跑在数据库里。

NewSQL的祖师爷Google Spanner就是为了解决海量数据扩展性的问题,但又有多少企业能有Google的业务数据量?恐怕还是只有典型的互联网公司,或者某些大企业的部分业务会有这种量级的数据存储需求。所以和MySQL一样,NewSQL的问题就回到了谁来买单这个根本问题上。恐怕到最后只能还是由投资人和国资委来买吧。

但最起码,NewSQL的这种尝试始终是值得赞扬的。

vs 云数据库

我想直率地说:多年来,我们就像个傻子一样,他们拿着我们开发的东西大赚了一笔”。

—— Ofer Bengal , Redis Labs 首席执行官

另一个值得关注的“竞争者”是所谓云数据库,包括两种,一种是放在云上托管的开源数据库。例如 RDS for PostgreSQL,另一种是自研的新一代云数据库。

针对前者,主要的问题是“云厂商吸血”。如果云厂商售卖开源软件,实际上会导致就会导致开源软件的相关岗位和利润向云厂商集中,而云厂商是否允许自己的程序员给开源项目做贡献,做多少贡献,其实是很难说的。负责人的大厂通常是会回馈社区,回馈生态的,但这取决于它们的自觉。开源软件还是应当将命运握在自己手中,防止云厂商过分做大形成垄断。相比少量垄断巨头,多数分散的小团体能提供更高的生态多样性,更有利于生态健康发展。

Gartner称2022年75%的数据库将部署至云平台,这个牛逼吹的太大了。(但也有圆的办法,毕竟用一台机器就可以轻松创建几亿个sqlite文件数据库,这算不算?)。因为云计算解决不了一个根本性的问题 —— 信任。实际上在商业活动中,技术牛逼不牛逼是很次要的因素,Trust才是最关键的。数据是很多企业的生命线,云厂商又不是真正的中立第三方,谁能保证数据不会被其偷窥,盗窃,泄漏,甚至直接被卡脖子关停(如各路云厂商锤Parler)?TDE之类的透明加密解决方案也属于鸡肋,充分的恶心了自己,但也防不住真正的有心人。也许要等真正实用的高效全同态加密技术成熟才能解决信任与安全这个问题吧。

另一个根本性的问题在于成本:就目前云厂商的定价策略,云数据库只有在小微规模下有优势。例如一台D740 64核|400G内存|3TB PCI-E SSD的高配机型四年综合成本撑死了十几万块。然而我能找到最大的规格RDS(比这差很多,32核|128GB)一年的价格就这个数了。只要数据量节点数稍微上那么点规模,雇个DBA自建就合算太多了。

云数据库的主要优势还是在于管控,说白了就是用起来方便,点点鼠标。日常运维功能已经覆盖的比较全面,也有一些基础的监控支持。总之下限是摆在那里,如果找不到靠谱的数据库人才,用云数据库起码不至于出太多幺蛾子。 不过这些管控软件虽好,基本都是闭源的,而且与供应商深度绑定。

如果你想找一个开源的PostgreSQL监控管控一条龙解决方案,不妨试试Pigsty。

后一种云数据库以AWS Aurora为代表,也包括一系列类似产品如阿里云PolarDB,腾讯云CynosDB。基本都是采用PostgreSQL与MySQL作为Base和协议层,基于云基础设施(共享存储,S3,RDMA)进行定制化,对扩容速度性能进行了优化。这类产品在技术上肯定是有新颖性和创造性的。但灵魂问题就是,这类产品相比直接使用原生PostgreSQL的收益到底在哪里呢?能看到立竿见影的好处就是集群扩容会快很多(从几小时级到5分钟),不过相比高昂的费用与供应商锁定的问题,实在是挠不到痛点和痒点。

总的来说,云数据库对原生PostgreSQL 构成的威胁是有限的。也不用太担心云厂商的问题,云厂商总的来说还开源软件生态的一份子,对社区和生态是有贡献的。赚钱嘛,不磕碜,大家都有钱赚了,才有余力去搞公益,对不对?


弃暗投明?

通常来说,Oracle的程序员转PostgreSQL不会有什么包袱,因为两者功能类似,大多数经验都是通用的。实际上,很多PostgreSQL生态的成员都是从Oracle阵营转投PG的。例如国内著名的Oracle服务商云和恩墨(由中国第一位Oracle ACE总监盖国强创办),去年就公开宣布“躬身入局”,拥抱PostgreSQL。

也有不少MySQL阵营转投PgSQL的,其实这类用户对两者的区别感受才是最深的:基本上都是一副相见恨晚,弃暗投明的样子。实际上我自己最开始也是先用MySQL😆,能自己选型后就拥抱了PgSQL。不过有些老程序员已经和MySQL形成了深度利益绑定,嚷嚷着MySQL多好多好,还要不忘来碰瓷喷一喷PgSQL(特指某人)。这个其实是可以理解的,触动利益比触动灵魂还难,看到自己擅长的技术日落西山那肯定是愤懑不平😠。毕竟一把年纪投在MySQL上,PostgreSQL🐘再好,让我抛弃我心爱的小海豚🐬,做不到啊。

不过,刚入行的年轻人还是有机会去选择一条更光明的道路的。时间是最公平的裁判,而新生代的选择则是最有代表性的标杆。据我个人观察,在新兴的极有活力的Golang开发者群体中,PostgreSQL的流行程度要显著高于MySQL,不少创业型、创新型的公司现在都选择Go+Pg作为自己的技术栈,例如Instagram,TanTan,Apple都是Go+PG。

我认为这一现象的主要原因就是新生代开发者的崛起,Go之于Java,就像PgSQL之于MySQL。长江后浪推前浪,这其实就是演化的核心机制 —— 新陈代谢。Go和PgSQL慢慢拍扁Java和MySQL,但Go和PgSQL当然也有可能在以后被诸如Rust和某些真正革命性的NewSQL数据库拍扁。但说到底,搞技术还是要搞那些前景光明的,不要去搞那些日暮西山的。(当然下海太早当烈士也不合适)。要去看新生代开发者在用什么,有活力的创业公司、新项目、新团队在用什么,弄这些是没有错的。


PG的问题

当然PgSQL有没有自己的问题?当然也有 —— 流行度

流行度关乎着着用户规模,信任水平,成熟案例数量,有效需求反馈量,开发者数量等等。尽管按目前的流行度发展趋势,PG将在几年后超过MySQL,所以从长期来看,我觉得这并不是问题。但作为PostgreSQL社区的一员,我觉得很有必要去进一步做一些事情,Secure this success,并加快这一进度。而要想让一样技术更加流行,效果最好的方式就是:降低门槛

所以,我做了一个开源软件Pigsty,要把PostgreSQL部署、监控、管理、使用的门槛从天花板砸到地板,它有三个核心目标:

  • 做最顶尖最专业的开源PostgreSQL 监控系统(类tidashboard)
  • 做门槛最低最好用的开源PostgreSQL管控方案(类tiup)
  • 做开箱即用的与数据分析&可视化集成开发环境(类minikube)

当然这里细节限于篇幅就不展开了,详情留待下篇分说。

PostgreSQL好处都有啥

微信公众号原文

PostgreSQL的Slogan是“世界上最先进的开源关系型数据库”,但我觉得这口号不够响亮,而且一看就是在怼MySQL那个“世界上最流行的开源关系型数据库”的口号,有碰瓷之嫌。要我说最能生动体现PG特色的口号应该是:一专多长的全栈数据库,一招鲜吃遍天嘛。

pggood


全栈数据库

成熟的应用可能会用到许许多多的数据组件(功能):缓存,OLTP,OLAP/批处理/数据仓库,流处理/消息队列,搜索索引,NoSQL/文档数据库,地理数据库,空间数据库,时序数据库,图数据库。传统的架构选型呢,可能会组合使用多种组件,典型的如:Redis + MySQL + Greenplum/Hadoop + Kafuka/Flink + ElasticSearch,一套组合拳基本能应付大多数需求了。不过比较令人头大的就是异构系统集成了:大量的代码都是重复繁琐的胶水代码,干着把数据从A组件搬运到B组件的事情。

在这里,MySQL就只能扮演OLTP关系型数据库的角色,但如果是PostgreSQL,就可以身兼多职,One handle them all,比如:

  • OLTP:事务处理是PostgreSQL的本行

  • OLAP:citus分布式插件,ANSI SQL兼容,窗口函数,CTE,CUBE等高级分析功能,任意语言写UDF

  • 流处理:PipelineDB扩展,Notify-Listen,物化视图,规则系统,灵活的存储过程与函数编写

  • 时序数据:timescaledb时序数据库插件,分区表,BRIN索引

  • 空间数据:PostGIS扩展(杀手锏),内建的几何类型支持,GiST索引。

  • 搜索索引:全文搜索索引足以应对简单场景;丰富的索引类型,支持函数索引,条件索引

  • NoSQL:JSON,JSONB,XML,HStore原生支持,至NoSQL数据库的外部数据包装器

  • 数据仓库:能平滑迁移至同属Pg生态的GreenPlum,DeepGreen,HAWK等,使用FDW进行ETL

  • 图数据:递归查询

  • 缓存:物化视图

ext

以Extension作六器,礼天地四方。

以Greenplum礼天,

以Postgres-XL礼地,

以Citus礼东方,

以TimescaleDB礼南方,

以PipelineDB礼西方,

以PostGIS礼北方。

—— 《周礼.PG》

在探探的旧版架构中,整个系统就是围绕PostgreSQL设计的。几百万日活,几百万全局DB-TPS,几百TB数据的规模下,数据组件只用了PostgreSQL。独立的数仓,消息队列和缓存都是后来才引入的。而且这只是验证过的规模量级,进一步压榨PG是完全可行的。

因此,在一个很可观的规模内,PostgreSQL都可以扮演多面手的角色,一个组件当多种组件使。虽然在某些领域它可能比不上专用组件,至少都做的都还不赖。而单一数据组件选型可以极大地削减项目额外复杂度,这意味着能节省很多成本。它让十个人才能搞定的事,变成一个人就能搞定的事。

为了不需要的规模而设计是白费功夫,实际上这属于过早优化的一种形式。只有当没有单个软件能满足你的所有需求时,才会存在分拆集成的利弊权衡。集成多种异构技术是相当棘手的工作,如果真有那么一样技术可以满足你所有的需求,那么使用该技术就是最佳选择,而不是试图用多个组件来重新实现它。

当业务规模增长到一定量级时,可能不得不使用基于微服务/总线的架构,将数据库的功能分拆为多个组件。但PostgreSQL的存在极大地推后了这个权衡到来的阈值,而且分拆之后依然能继续发挥重要作用。


运维友好

当然除了功能强大之外,Pg的另外一个重要的优势就是运维友好。有很多非常实用的特性:

  • DDL能放入事务中,删表,TRUNCATE,创建函数,索引,都可以放在事务里原子生效,或者回滚。

    这就能进行很多骚操作,比如在一个事务里通过RENAME,完成两张表的王车易位。

  • 能够并发地创建、删除索引,添加非空字段,重整索引与表(不锁表)。

    这意味着可以随时在线上不停机进行重大的模式变更,按需对索引进行优化。

  • 复制方式多样:段复制,流复制,触发器复制,逻辑复制,插件复制等等。

    这使得不停服务迁移数据变得相当容易:复制,改读,改写三步走,线上迁移稳如狗。

  • 提交方式多样:异步提交,同步提交,法定人数同步提交。

    这意味着Pg允许在C和A之间做出权衡与选择,例如交易库使用同步提交,普通库使用异步提交。

  • 系统视图非常完备,做监控系统相当简单。

  • FDW的存在让ETL变得无比简单,一行SQL就能解决。

    FDW可以方便地让一个实例访问其他实例的数据或元数据。在跨分区操作,数据库监控指标收集,数据迁移等场景中妙用无穷。同时还可以对接很多异构数据系统。


生态健康

PostgreSQL的生态也很健康,社区相当活跃。

相比MySQL,PostgreSQL的一个巨大的优势就是协议友好。PG采用类似BSD/MIT的PostgreSQL协议,差不多理解为只要别打着Pg的旗号出去招摇撞骗,随便你怎么搞,换皮出去卖都行。君不见多少国产数据库,或者不少“自研数据库”实际都是Pg的换皮或二次开发产品。

当然,也有很多衍生产品会回馈主干,比如timescaledb, pipelinedb, citus 这些基于PG的“数据库”,最后都变成了原生PG的插件。很多时候你想实现个什么功能,一搜就能找到对应的插件或实现。开源嘛,还是要讲一些情怀的。

PG的代码质量相当之高,注释写的非常清晰。C的代码读起来有种Go的感觉,代码都可以当文档看了。能从中学到很多东西。相比之下,其他数据库,比如MongoDB,看一眼我就放弃了读下去的兴趣。

而MySQL呢,社区版采用的是GPL协议,这其实挺蛋疼的。要不是GPL传染,怎么会有这么多基于MySQL改的数据库开源出来呢?而且MySQL还在乌龟壳的手里,让自己的蛋蛋攥在别人手中可不是什么明智的选择,更何况是业界毒瘤呢?Facebook修改React协议的风波就算是一个前车之鉴了。


问题

当然,要说有什么缺点或者遗憾,那还是有几个的:

  • 因为使用了MVCC,数据库需要定期VACUUM,需要定期维护表和索引避免性能下降。
  • 没有很好的开源集群监控方案(或者太丑!),需要自己做。
  • 慢查询日志和普通日志是混在一起的,需要自己解析处理。
  • 官方Pg没有很好用的列存储,对数据分析而言算一个小遗憾。

当然都是些无关痛痒的小毛小病,不过真正的问题可能和技术无关……

说到底,MySQL确实是最流行的开源关系型数据库,没办法,写Java的,写PHP的,很多人最开始用的都是MySQL…,所以Pg招人相对困难是一个事实,很多时候只能自己培养。不过看DB Engines上的流行度趋势,未来还是很光明的。

dbrank

其他

学PostgreSQL是一件很有趣的事,它让我意识到数据库的功能远远不止增删改查。我学着SQL Server与MySQL迈进数据库的大门。但却是PostgreSQL真正向我展示了数据库的奇妙世界。

之所以写本文,是因为在知乎上的老坟又被挖了出来,让笔者回想起当年邂逅PostgreSQL时的青葱岁月。(https://www.zhihu.com/question/20010554/answer/94999834 )当然,现在我干了专职的PG DBA,忍不住再给这老坟补几铲。“王婆卖瓜,自卖自夸”,夸一夸PG也是应该的。嘿嘿嘿……

全栈工程师就该用全栈数据库嘛。

我自己比较选型过MySQL和PostgreSQL,难得地在阿里这种MySQL的世界中有过选择的自由。我认为单从技术因素上来讲,PG是完爆MySQL的。尽管阻力很大,最后还是把PostgreSQL用了起来,推了起来。我用它做过很多项目,解决了很多需求(小到算统计报表,大到给公司创收个小目标)。大多数需求PG单挑就搞定了,少部分也会再用些MQ和NoSQL(Redis,MongoDB,Cassandra/HBase)。Pg实在是让人爱不释手。

最后实在是对Pg爱不释手,以至于专职去研究PG了。

在我的第一份工作中就深刻尝到了甜头,使用PostgreSQL,一个人的开发效率能顶一个小团队:

  • 后端懒得写怎么办,PostGraphQL直接从数据库模式定义生成GraphQL API,自动监听DDL变更,生成相应的CRUD方法与存储过程包装,对于后台开发再方便不过,类似的工具还有PostgREST与pgrest。对于中小数据量的应用都还堪用,省了一大半后端开发的活。

  • 需要用到Redis的功能,直接上Pg,模拟普通功能不在话下,缓存也省了。Pub/Sub使用Notify/Listen/Trigger实现,用来广播配置变更,做一些控制非常方便。

  • 需要做分析,窗口函数,复杂JOIN,CUBE,GROUPING,自定义聚合,自定义语言,爽到飞起。如果觉得规模大了想scale out可以上citus扩展(或者换greenplum);比起数仓可能少个列存比较遗憾,但其他该有的都有了。

  • 用到地理相关的功能,PostGIS堪称神器,千行代码才能实现的复杂地理需求,一行SQL轻松高效解决

  • 存储时序数据,timescaledb扩展虽然比不上专用时序数据库,但百万记录每秒的入库速率还是有的。用它解决过硬件传感器日志存储,监控系统Metrics存储的需求。

  • 一些流计算的相关功能,可以用PipelineDB直接定义流式视图实现:UV,PV,用户画像实时呈现。

  • PostgreSQL的FDW是一种强大的机制,允许接入各种各样的数据源,以统一的SQL接口访问。它妙用无穷:

    • file_fdw这种自带的扩展,可以将任意程序的输出接入数据表。最简单的应用就是监控系统信息
    • 管理多个PostgreSQL实例时,可以在一个元数据库中用自带的postgres_fdw导入所有远程数据库的数据字典。统一访问所有数据库实例的元数据,一行SQL拉取所有数据库的实时指标,监控系统做起来不要太爽。
    • 之前做过的一件事就是用hbase_fdw和MongoFDW,将HBase中的历史批量数据,MongoDB中的当日实时数据包装为PostgreSQL数据表,一个视图就简简单单地实现了融合批处理与流处理的Lambda架构。
    • 使用redis_fdw进行缓存更新推送;使用mongo_fdw完成从mongo到pg的数据迁移;使用mysql_fdw读取MySQL数据并存入数仓;实现跨数据库,甚至跨数据组件的JOIN;使用一行SQL就能完成原本多少行代码才能实现的复杂ETL,这是一件多么美妙的事情。
  • 各种丰富的类型与方法支持:例如JSON,从数据库直接生成前端所需的JSON响应,轻松而惬意。范围类型,优雅地解决很多原本需要程序处理的边角情况。其他的例如数组,多维数组,自定义类型,枚举,网络地址,UUID,ISBN。很多开箱即用的数据结构让程序员省去了多少造轮子的功夫。

  • 丰富的索引类型:通用的Btree索引;大幅优化顺序访问的Brin索引;等值查询的Hash索引;GIN倒排索引;GIST通用搜索树,高效支持地理查询,KNN查询;Bitmap同时利用多个独立索引;Bloom高效过滤索引;能大幅减小索引大小的条件索引;能优雅替代冗余字段的函数索引。而MySQL就只有那么可怜的几种索引。

  • 稳定可靠,正确高效。MVCC轻松实现快照隔离,MySQL的RR隔离等级实现不完善,无法避免PMP与G-single异常。而且基于锁与回滚段的实现会有各种坑;PostgreSQL通过SSI能实现高性能的可序列化。

  • 复制强大:WAL段复制,流复制(v9出现,同步、半同步、异步),逻辑复制(v10出现:订阅/发布),触发器复制,第三方复制,各种复制一应俱全。

  • 运维友好:可以将DDL放在事务中执行(可回滚),创建索引不锁表,添加新列(不带默认值)不锁表,清理/备份不锁表。各种系统视图,监控功能都很完善。

  • 扩展众多、功能丰富、可定制程度极强。在PostgreSQL中可以使用任意的语言编写函数:Python,Go,Javascript,Java,Shell等等。与其说Pg是数据库,不如说它是一个开发平台。我就试过很多没什么卵用但很好玩的东西:数据库里(in-db) 的爬虫/ 推荐系统 / 神经网络 / Web服务器等等。有着各种功能强悍或脑洞清奇的第三方插件:[https://pgxn.org/)。

  • PostgreSQL的License友好,BSD随便玩,君不见多少数据库都是PG的换皮产品。MySQL有GPL传染,还要被Oracle捏着蛋蛋。