介绍

Postgresql (也可以叫它的旧名称: POSTGRES), 一款典型的 RDBMS (关系型数据库管理系统), 其名称中的 sql 是在 1996 年由它的作者变更的, 代表着 structured query language (结构化查询语言), 从那时起 Postgresql 是一款支持 sql 的数据库.

在认识 Postgresql 之前, sqlite 一直是我的首选数据库, 因为快速,轻量,便捷, 但是无法多项目共享, 所以在小型项目中, 它是一个不错的选择. 后续在工作中又接触到了 mysql, 但是由于 mysql 的开源协议以及 mariadb 的性能问题, 迫使我不得不去寻找替代品, 于是我找到了 Postgresql, 再了解一通后, 我发现我之前好像完全误解了他.

Postgresql

在此之前我一直被官网的"大象"给误以为他是一个特别重型,部署以及什么特别复杂的数据库

契机是我管理的一台公司的服务器, 上面有个使用频繁的服务用到了 pgsql 而且我也在之前跑了一个 mariadb 在上面, 但是某天通过面板发现那个使用频繁的 pgsql 居然比另外一个好久没用也没数据的 mariadb 占用内存还要低, 所以就带着好奇心去了解了 pgsql 这款数据库.

而且后续发现由于他的开放原因他有不少三方分发的二进制包, 并且安装以及配置都非常简单, 只需要两行命令即可启动一个完整的数据库.


initdb -D ${data} # 初始化数据库

# no daemon mode
postgresql -D ${data} # 启动数据库

# daemon mode
pg_ctl -D ${data} -l ${log} start # 启动数据库


简单, 方便, 仅此而已!

优点

不得不再说宽松开放协议的好处, 他的生态还算比较完整, 甚至由于他的一些特性社区还出现好多专为 Postgresql 开发的 ORMGUI 工具, 例如 pgAdmin, 而且他的 sql 语法也是非常接近 mysql 的, 你可以很容易的从 mysql 迁移到 Postgresql.

他的数据类型也是非常丰富的, 除了常用的那些类型外还有例如 json, jsonb, hstore, uuid, inet, tsvector, tsquery, xml, array, range, geometry, geography 等等, 并且他能在性能和 mysql 持平的情况下把 TEXT 类型的长度扩展到了 “无限”, 也就是说你可以存储任意长度的字符串, 而不用担心 mysqlTEXT 类型的长度限制.

还有订阅/发布能在微服务系统中省下一个 etcd 的位置

在此感觉 Postgresql 更像文档和关系型的结合体…一款复合型数据库.

缺点

他相较此前所使用的 mysql 或者 sqlite 在 SQL, 结构, 字符集都有较大差异, 所以需要不少时间来适应…

性能对比

由于不想再装 mysql 了, 就拿之前的绿色版 mariadb 来做对比, sqlite 用的是 Golang 的 C 转译 Plan9 ASM 的库, 在这里面 sqlite 的写入性能直接薄纱后者…不过加了索引就会慢下来的…

测试环境:

设备配置:


OS: Arch Linux x86_64
Host: A7S
Kernel: 6.0.1-zen2-1-zen
Uptime: 2 hours, 36 mins
Packages: 1103 (pacman)
Shell: bash 5.1.16
Resolution: 1920x1080 @ 144.00Hz
DE: Plasma 5.26.0
WM: KWin
Theme: [Plasma], Breeze [GTK2/3]
Icons: [Plasma], Papirus-Dark [GTK2/3]
Terminal: konsole
Terminal Font: Hack 11
CPU: AMD Ryzen 7 5800H with Radeon Graphics
GPU: NVIDIA GeForce RTX 3060 Mobile / Max-Q
Memory: 19042MiB / 39951MiB (47%)
GPU Driver: NVIDIA 520.56.06

表结构:

-- sqlite
CREATE TABLE IF NOT EXISTS user (
  id INTEGER PRIMARY KEY,
  phone TEXT,
  wb_code TEXT
);

-- mariadb
CREATE TABLE user (
	id BIGINT PRIMARY KEY AUTO_INCREMENT,
  phone VARCHAR(15),
  wb_code VARCHAR(15)
);

-- postgresql
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  phone TEXT,
  wb_code TEXT
);

-- query sql
SELECT count(*) FROM users;

三个数据库都没有加任何索引, 仅主键默认唯一和自增.
mariadb 由于用 TEXT 太慢了, 就换成了 VARCHAR

软件版本:

name version
sqlite sqlite3 (c2plan9_asm SQLite 3.38.5)
mariadb 10.4.24 (mysqld 10.4.24-MariaDB)
postgresql 14.5.0 (embedded-postgres-binaries-linux-amd64-14.5.0.jar)
基准速度 (写入):
rows sqlite (mem) mariadb (ram disk) postgresql (ssd)
100000 361.339819ms 331.59892ms 332.472862ms
1000000 4.108169564s 4.199602306s 3.138833165s
10000000 41.893184137s 48.15801141s 31.01379084s
100000000 7m8.18355064s 8m13.110271561s 5m33.067763299s
[query sql] 573ms 9258ms 1539ms

在小量数据下面, 三个表现差不多, 但是 mariadb 要比 pgsql 快 1ms.
但是随着数据量达到 1 亿条时候, mariadb 开始跟不上了, sqlite 也慢了, 而 pgsql 此刻才真正展示了他的强大.

内存占用:
rows sqlite (mem) mariadb (ram disk) postgresql (ssd)
100000000 ~103M (main) ~282M (mysqld.bin) ~33.3M (7.7 + 1.4 + 1.1 + 1.4 + 1.5 + 3 + 3.2 + 3.9 + 10.1)

当然…cache 并没有参与计算…因为 sqlite 因为 golang 的原因测不出来…
pgsql 由于是进程分隔的所以他有一堆子进程, 并且每个连接也是一个独立的进程, 所以就是这一堆相加…

磁盘占用:
rows sqlite (mem) mariadb (ram disk) postgresql (ssd)
100000000 3082.40625M ~5.3G ~9.7G

pgsql 这是真的空间换时间了…草…

结论:

  1. sqlite 适合单站应用, 他在无索引情况下性能比肩 mariadb, 而且磁盘占用小, 如果需要复杂索引还是 mariadb/mysql 好一点.
  2. mariadb 感觉性能比 mysql 差了好多, 而且内存占用也稍多, 好处是通用, 大部分人学生时代都会用到 mysql, 所以学习成本低.
  3. pgsql 体量很大, 看测试数据有点典型的空间换时间的样子 hhhh, 而且查询也挺快, 但是学习成本高, 大部分特性也不是很通用, 方言特别方…好处是 Golang 有很多专用 ORM 框架, 使用起来也很方便.