文中参考文档点击阅读原文打开, 同时推荐2个学习环境:
1、懒人Docker镜像, 已打包200+插件:《最好的PostgreSQL学习镜像》
2、有web浏览器就能用的云起实验室: 《免费体验PolarDB开源数据库》
3、PolarDB开源数据库内核、最佳实践等学习图谱: https://www.aliyun.com/database/openpolardb/activity
PG干不过MySQL/Oracle/国产? 教你几招性能PK“作弊技巧”!
PG PK MySQL/Oracle/国产? 假设硬件环境一样, 如何取得更大胜算? 教你几招“作弊技巧”!
“作弊技巧”以tpch, 高并发小事务, 批量导入三个PK场景为例.
PS: 很多场景是PG的强项, PK这些场景担心被人说胜之不武。发挥插件和索引人无我有功能的场景, 如模糊搜索、GIS、数组标签、向量相似等. 看我github宝典:
《2023-PostgreSQL Docker镜像学习环境 ARM64版, 已集成热门插件和工具》
《2023-PostgreSQL Docker镜像学习环境 AMD64版, 已集成热门插件和工具》
《2017-PostgreSQL 应用场景实践 - 适合架构师与业务开发者》
《2020-PostgreSQL+MySQL 联合解决方案课程 - 适合架构师与业务开发者》
《2020-PostgreSQL 应用场景最佳实践 - 适合架构师与业务开发者》
《2021-重新发现PG之美 系列 - 适合架构师与业务开发者》
《Oracle DBA 增值+转型 PostgreSQL 学习方法、路径》
《PostgreSQL、Greenplum 技术+108个场景结合最佳实践《如来神掌》》
既然是作弊, 有一些技巧有丢数据库风险/数据库不一致风险的, 有一些属于耍流氓, 所以千万不要让对手知道, 否则被打0分可别怪我. 你有坚硬的商务关系当我没说, 算我"助纣为虐"了.
一、TPCH
详细操作请参考我的github: 《PG被DuckDB碾压,该反省哪些方面? DuckDB v0.10.3 在Macmini 2023款上的tpch性能表现如何? PostgreSQL使用duckdb_fdw 的tpch加速性能表现如何?》
或:
要大幅度提升OLTP数据库的tpch性能, 这不是扯淡吗? 改造优化器、列存储、向量化是必须滴, 不过PG还真可以作弊, 例如:
1、把数据库装进parquet
2、把结构装进duckdb
3、把tpch的22条query做成视图
4、用fdw调用duckdb
搞定, 一气呵成, 大概能提升个40几倍的性能吧. 别让人知道, 你这是在耍流氓.
二、高并发小事务
1、配置较大的shared buffer.
2、高并发, 就PG这种进程模型数据库, 我都吐槽过无数遍, 并发连接上千后性能急剧下降, 早晚得上内置连接池. 外置连接池增加了1跳, 而且外置连接池很难做到无缝迁移事务和会话变量, 限制较多. 第一优先推荐使用内置连接池, 参考:
连接池/限制连接数 《PostgresPro buildin pool(内置连接池)版本 原理与测试》
阿里云PolarDB shared server: https://apsaradb.github.io/PolarDB-for-PostgreSQL/zh/features/v11/performance/shared-server.html
如果不能使用内置连接池, 一定要选一个好一点(支持多进程/多线程)的外置连接池.
3、拉长 checkpoint 周期, 可以配置:
#checkpoint_timeout = 1d # range 30s-1d
max_wal_size = 1GB
min_wal_size = 64GB
#checkpoint_flush_after = # measured in pages, 0 disables
4、拉长 checkpoint_completion_target , 可以配置:
#checkpoint_completion_target = 0.9 # checkpoint target duration, 0.0 - 1.0
5、观察pg_catalog.pg_stat_bgwriter
, 尽量减少buffers_backend_fsync, 调整bgwriter的工作量和间歇, 尽量让bgwriter去淘汰脏页, 可以配置:
#bgwriter_delay = 10ms # 10-10000ms between rounds
#bgwriter_lru_maxpages = 500 # max buffers written/round, 0 disables
#bgwriter_lru_multiplier = 2.0 # 0-10.0 multiplier on buffers scanned/round
#bgwriter_flush_after = 512kB # measured in pages, 0 disables
6、关闭hint和checksum, 降低CPU和datafile, wal日志量.
#wal_log_hints = off # also do full page writes of non-critical updates
# (change requires restart)
initdb --help
-k, --data-checksums use data page checksums
以上都属于君子配置, 没什么危害. 下面来一点作弊配置.
1、少写点wal.
#wal_level = minimal # minimal
2、关闭 wal同步提交, 小事务写性能飙升.
synchronous_commit = off
数据库崩溃会丢数据, 但是不会导致数据不一致. 丢多少则取决于以下配置:
#wal_writer_delay = 200ms # 1-10000 milliseconds
#wal_writer_flush_after = 1MB # measured in pages, 0 disables
3、关闭fpw, 以确保检查点期间性能丝滑. 如果你的文件系统是cow的, 大胆关闭fpw没有任何危害.
#full_page_writes = off
如果文件系统不是cow的, 关闭后可能导致坏块隐患. 参考阅读:
《一起学PolarDB - 第2期 - 为什么FPW是以牺牲(性能、存储空间、稳定性)换取的可靠性?》
《DB吐槽大会,第11期 - FPW | Double Write》
4、关闭fsync, 高度危险参数, 相当于写IO全部异步了, 把压力给到OS刷脏. 带来的后果是数据库可能有丢数据、坏块等风险. 但是写性能会急剧提升.
#fsync = on # flush data to disk for crash safety
# (turning this off can cause
# unrecoverable data corruption)
三、批量导入
1、使用最大的block size.
2、使用unlogged table
3、关闭全局或被导入表的autovacuum
4、删除被导入表上不必要的索引
5、批量导入, 例如使用copy导入、使用insert into table values (),(),()...()
;
6、使用pg_bulkload工具导入, 这个工具导入也是不写wal日志的.
7、先把数据文件生成, 再导入. 这个解决的是block extent lock瓶颈.
例如要导入1000万记录, 先导入进去, 然后删除除了最后一个数据块里的一条记录的其他所有记录, 然后vacuum这个表, 这样即使vacuum, 也不会回收物理空间, 而是把所有page都清空为可插入状态, 再次导入时就不需要分配block了.
参考我的吐槽信息:
《DB吐槽大会,第28期 - PG 每次只扩展1个block》
以上“作弊手段”, 学会了吗? 如果你PK赢了一定要来打赏一下哟.
本期彩蛋- PG中文社区年度峰会7.12,13在杭州举行,欢迎参加

文章中的参考文档请点击阅读原文获得.
欢迎关注我的github (https://github.com/digoal/blog) , 学习数据库不迷路.
近期正在写公开课材料, 未来将通过视频号推出, 欢迎关注视频号:






