Postgresql
(也可以叫它的旧名称: POSTGRES
), 一款典型的 RDBMS
(关系型数据库管理系统), 其名称中的 sql
是在 1996 年由它的作者变更的, 代表着 structured query language
(结构化查询语言), 从那时起 Postgresql
是一款支持 sql
的数据库.
在认识 Postgresql
之前, sqlite
一直是我的首选数据库, 因为快速,轻量,便捷, 但是无法多项目共享, 所以在小型项目中, 它是一个不错的选择. 后续在工作中又接触到了 mysql
, 但是由于 mysql
的开源协议以及 mariadb
的性能问题, 迫使我不得不去寻找替代品, 于是我找到了 Postgresql
, 再了解一通后, 我发现我之前好像完全误解了他.
在此之前我一直被官网的"大象"
给误以为他是一个特别重型,部署以及什么特别复杂的数据库
契机是我管理的一台公司的服务器, 上面有个使用频繁的服务用到了 pgsql 而且我也在之前跑了一个 mariadb 在上面, 但是某天通过面板发现那个使用频繁的 pgsql 居然比另外一个好久没用也没数据的 mariadb 占用内存还要低, 所以就带着好奇心去了解了 pgsql 这款数据库.
而且后续发现由于他的开放原因他有不少三方分发的二进制包, 并且安装以及配置都非常简单, 只需要两行命令即可启动一个完整的数据库.
initdb -D ${data} # 初始化数据库# no daemon modepostgresql -D ${data} # 启动数据库# daemon modepg_ctl -D ${data} -l ${log} start # 启动数据库
简单, 方便, 仅此而已!
不得不再说宽松开放协议的好处, 他的生态还算比较完整, 甚至由于他的一些特性社区还出现好多专为 Postgresql
开发的 ORM
和 GUI
工具, 例如 pgAdmin
, 而且他的 sql
语法也是非常接近 mysql
的, 你可以很容易的从 mysql
迁移到 Postgresql
.
他的数据类型也是非常丰富的, 除了常用的那些类型外还有例如 json
, jsonb
, hstore
, uuid
, inet
, tsvector
, tsquery
, xml
, array
, range
, geometry
, geography
等等, 并且他能在性能和 mysql
持平的情况下把 TEXT
类型的长度扩展到了 “无限”, 也就是说你可以存储任意长度的字符串, 而不用担心 mysql
的 TEXT
类型的长度限制.
还有订阅/发布能在微服务系统中省下一个 etcd 的位置
在此感觉 Postgresql
更像文档和关系型的结合体…一款复合型数据库.
他相较此前所使用的 mysql
或者 sqlite
在 SQL, 结构, 字符集都有较大差异, 所以需要不少时间来适应…
由于不想再装 mysql
了, 就拿之前的绿色版 mariadb
来做对比, sqlite
用的是 Golang 的 C 转译 Plan9 ASM 的库, 在这里面 sqlite
的写入性能直接薄纱后者…不过加了索引就会慢下来的…
设备配置:
OS: Arch Linux x86_64Host: A7SKernel: 6.0.1-zen2-1-zenUptime: 2 hours, 36 minsPackages: 1103 (pacman)Shell: bash 5.1.16Resolution: 1920x1080 @ 144.00HzDE: Plasma 5.26.0WM: KWinTheme: [Plasma], Breeze [GTK2/3]Icons: [Plasma], Papirus-Dark [GTK2/3]Terminal: konsoleTerminal Font: Hack 11CPU: AMD Ryzen 7 5800H with Radeon GraphicsGPU: NVIDIA GeForce RTX 3060 Mobile / Max-QMemory: 19042MiB / 39951MiB (47%)GPU Driver: NVIDIA 520.56.06
表结构:
-- sqliteCREATE TABLE IF NOT EXISTS user ( id INTEGER PRIMARY KEY, phone TEXT, wb_code TEXT);-- mariadbCREATE TABLE user (id BIGINT PRIMARY KEY AUTO_INCREMENT, phone VARCHAR(15), wb_code VARCHAR(15));-- postgresqlCREATE TABLE users ( id SERIAL PRIMARY KEY, phone TEXT, wb_code TEXT);-- query sqlSELECT 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 这是真的空间换时间了…草…