1. 安装
1.1. docker
version: '3'
services:
postgresql:
image: postgres:alpine
container_name: postgresql
volumes:
- ~/volumes/postgresql/:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=jy
- POSTGRES_PASSWORD=123456
- TZ=Asia/Shanghai
network_mode: host
1.2. 安装包安装
groupadd postgres
useradd postgres -g postgres
passwd postgres
mkdir -p /database/pg/pg_root
chown -R postgres:postgres /database/pg
sudo apt install postgresql-all
initdb -D /database/pg/pg_root -E UTF8 --locale=C -U postgres -W
2. 基本命令
# 创建db
createdb -U <username> <dbName>
# 删除b
dropdb -U <username> <dbName>
# 重建索引
reindexdb -d <dbName>
# 对数据库物理文件垃圾回收
vacuumdb <dbName>
# 清除数据库中未引用的大对象
vacuumlo <dbName>
pgdump
pgrestore
pgbench
# 登录数据库
psql [-h HOST] [-p PORT] DB [USERNAME]
# 获取pg配置
pg_config
# 获取数据库状态
pg_ctl -D <data-dir> status
# 启动数据库
postgres -D <data-dir> &
# 关闭数据库
pg_ctl -D <data-dir> -m [fast|smart|immediate] -t <timeout> stop
3. 配置
3.1. pg_hba.conf
TYPE DATABASE USER ADDRESS METHOD
-
TYPE: 允许连接的方式
-
local: Unix domain socket
-
host: TCP/IP, localhost default
-
hostssl: OpenSSL restrict
-
hostnossl: SSL not permitted
-
-
METHOD: 认证方法
-
trust
-
password: 明文密码
-
md5
-
reject: 拒绝访问
-
scram-sha-256
-
3.2. postgresql.conf
postgresql 启动时postgresql.auto.conf会覆盖postgresql.conf内容 更改配置生效: pg_ctl -D <data-dir> reload
4. psql命令
-
psql -c "SQL" [-d DB_NAME] [-U USERNAME] [-W PASSWORD] [-f SQL_FILE]
-
\db: 查看表空间
-
\l: 查看数据库
-
\d <DB_NAME>: 查看表定义
-
\dt+ <DB_NAME>: 查看表空间大小
-
\di+ <IDX_NAME>: 查看索引空间大小
-
\x: 切换查询显示模式
-
COPY <DB> FROM|TO "FILE_PATH" : (大表)导入导出数据(必须有superuser权限)
-
\copy <DB> FROM|TO "FILE_PATH" : (小表)导入导出数据
-
\set VAR_NAME VALUE: 设置变量, :VAR_NAME 使用
-
\timing: 开启sql计时
5. 数据类型
5.1. 数字类型
-
int2 int4 int8
-
decimal/numeric[(precision,scale)]
-
real 6位十进制精度浮点数
-
double precision 15位十进制精度浮点数
-
smallserial/serial/bigserial 2/4/8字节自增序列
-
bytea: 二进制
5.2. 字符串类型
-
varchar/character varying 变长, 如果不指定长度, 最大不能超过1GB.
-
character/char 定长
-
text 变长, 最大不能超过1GB
5.3. 日期类型
-
timestamp[without time zone] 不带时区的时间戳
-
timestamp[with time zone] / timestamptz 带时区的时间戳
-
date 日期
-
time[with[out] time zone] 一天的时间
-
interval 时间间隔
时区名称查看: select * from pg_timezone_names;
5.4. 几何类型
-
point: 点
-
line: 线
-
lseg: 线段
-
box: 矩形
-
path: 路径
-
polygon: 多边形
-
circle: 圆
5.5. range类型
-
int4range
-
int8range
-
numrange
-
tsrange
-
tstzrange
-
daterange
5.6. 其他
-
boolean
-
cidr/inet/macaddr/macaddr8
-
数组
-
json/jsonb
-
json以文本格式存储, jsonb以二进制存储.
-
json输入和输出的键顺序保持一致, jsonb不保证.
-
json会保留输入中的空格, jsonb不会.
-
jsonb会删除重复的键, 只保留最后一个.
6. 函数
-- 计算字符串中的字符数
select char_length('abcd'); -- 4
-- 计算字符串占用的字节数
select octet_length('abcd'); -- 4
-- 获取字符在字符串中的位置, 位置从1开始
select position('bc' in 'abcd'); -- 2
-- 提取字符串中的子串
select substring('abcd' from 2 for 3); -- bcd
-- 分割字符串
select split_part('abc,def,ghi', ',', 2); -- def
-- 时间字段提取
select extract(year from '2019-07-15:12:34:56'::timestamp); -- 2019
-- 数组两种形式
select array[1,2,3];
select '{1,2,3}';
-- 获取数组指定下标元素, 位置从1开始
select arr[1] from (select array[1,2,3] arr) a; -- 1
-- 数组追加元素
select array_append(array[1,2,3],4); -- {1,2,3,4}
select array[1,2,3]||4;
select array[1,2,3] || array[1,2,3]; -- {1,2,3,1,2,3}
-- 数组删除元素
select array_remove(array[1,2,2,2,3],2); -- {1,3}
-- 判断数组是否相等
select array[1,2,3] = array [1,2,2,2,3]; -- false
-- 判断数组是否不相等
select array[1,2,3] <> array [1,2,2,2,3]; -- true
-- 比较数组
select array[1,2,3] <= array[2,1]; -- true
select array[1,2,3] >= array[2,1]; -- false
-- 判断数组包含关系
select array[1,2,3] @> array[1]; -- true
select array[1,2,3] <@ array[1,2,3,4,5]; -- true
-- 判断数组是否有公共元素
select array[1,2,3] && array[22]; -- false
-- 获取数组维度
select array_dims(array[[4],[3],[2],[1]]); -- [1:4] [1:1]
-- 获取数组指定维度的长度
select array_length(array[1,2,3,4],1); -- 3
select array_length(array[[4],[3],[2],[1]],2); -- 1
-- 获取数组某一个元素第一次出现的位置, 位置从1开始
select array_position(array[1,2,3],3); -- 3
-- 替换数组指定元素
select array_replace(array[1,2,3],2,11); -- {1,11,3}
-- 数组转为字符串
select array_to_string(array[1,2,3,null],',','99'); -- 1,2,3
-- 范围
select int4range(1,10,'[]'); -- [1,11)
select daterange('2019-06-01','2019-07-02'); -- [2019-06-01,2019-07-02)
-- 获取范围下界
select lower(int4range(1,10));
-- 获取范围上界
select upper(int4range(1,10));
-- 判断范围是否为空
select isempty(int4range(1,10));
-- json表示
select '{"a":1}'::json;
-- json字段值获取
select j -> 'a' from ( select '{"a":1}'::json j) sub; -- 1
-- 提取json中的键值对
select * from json_each('{"a":1,"b":2}'::json); -- a 1 b 2
select * from json_each_text('{"a":"aaa","b":2}'::json); -- a 1 b 2
-- 删除jsonb中的key
select '{"a":1,"b":2}'::jsonb - 'a'; -- {"b":2}
-- 判断key是否为顶层key
select '{"a":1,"b":2, "c":{"d":4}}'::jsonb ? 'd'; -- false
-- 获取json所有key
select json_object_keys('{"a":1,"b":2}'); -- a b
-- 删除json指定key
select '{"a":1,"b":2, "c":{"d":4}}'::jsonb - 'a'; -- {"b": 2, "c": {"d": 4}}
-- 删除json嵌套key
select '{"a":1,"b":2, "c":{"d":4}}'::jsonb #- '{c,d}'::text[];
7. 高级特性
-
with从句
-
批量插入: insert into select from / insert into values (),() / COPY
-
upsert: insert into … on conflict do {NOTHING | update set <colName> = EXCLUDED.colName}
-
insert/update/delete .. returning *
-
select from <table> TABLESAMPLE {SYSTEM | BERNOULLI}
-
string_agg() / array_agg()
-
窗口函数
-
row_number() :
select row_number() OVER partition by <colName>
,eg: 1,2,3, 1 -
rank() : 分组重复则序号相同, 但下一个分组内不同行的序号保持增长,eg: 1,1,3
-
dense_rank() : 分组重复则序号相同, 下一个分组内不同行的序号继续增长,eg: 1,1,2
-
lag(field,offset,defaultValue): 获取行偏移offset那行某个字段的数据(offset为正向上偏移,为负则相反)
-
first_value(field): 取分组第一行数据
-
last_value(field): 取分组最后一行数据
-
nth_value(field,line): 取分组指定行数据
-
别名: select …[rank() over NAME] from <table> WINDOW <NAME> AS ()
-
8. Monitor
8.1. pg_stat_activity
查看实时连接.
列名 | 描述 |
---|---|
datid |
数据库id |
datname |
数据库名称 |
pid |
服务于这个连接的进程id |
usesysid |
连接的用户id |
usename |
连接的用户名 |
application_name |
应用名称 |
client_addr |
客户端ip |
client_hostname |
客户端主机名 |
client_port |
客户端端口号 |
backend_start |
连接何时被启动 |
xact_start |
事务何时被启动 |
query_start |
连接查询起始时间 |
state_change |
state列修改时间 |
wait_event_type |
|
wait_event |
|
state |
连接状态: * active: 后台进程正在执行该SQL. * idle: 后台进程处于空闲状态, 等待后续客户端发出命令. * idle in transaction: 后台进程正在事务中. * idle in transaction(aborted): 事务中的部分SQL异常. * fastpath function call: 正在执行fast-path函数. |
query |
当前或上一次的sql语句 |
backend_xid |
|
backend_xmin |
|
backend_type |
-- 查看活动会话
select pid, client_addr, query_start, state, query, wait_event, wait_event_type
from pg_stat_activity
where datid is not null
and pid <> pg_backend_pid()
order by query_start desc;
-- 查看数据库连接数
select datname, client_addr, count(*)
from pg_stat_activity
where pid <> pg_backend_pid()
group by datname, client_addr
order by 1, 2, 3 desc;
-- 查看会话状态统计
select datname,
count(*) AS open,
count(*) filter ( where state = 'active' ) AS active,
count(*) filter ( where state = 'idle' ) AS idle,
count(*) filter ( where state = 'idle in transaction' ) AS idle_in_tx
from pg_stat_activity
where backend_type = 'client backend'
group by rollup (1);
-- 查看当前事务
select pid, xact_start, now() - xact_start AS duration
from pg_stat_activity
where state like '%transaction%'
order by 3 desc;
8.2. pg_stat_database
查看数据库统计信息.
列名 | 描述 |
---|---|
datid |
数据库id |
datname |
数据库名 |
numbackends |
当前打开的数据库连接数 |
xact_commit |
倾向于事务提交 |
xact_rollback |
倾向于事务回滚 |
blks_read |
缓冲未命中数 |
blks_hit |
缓冲命中数 |
tup_returned |
返回行数 |
tup_fetched |
查询行数 |
tup_inserted |
插入行数 |
tup_updated |
更新行数 |
tup_deleted |
删除行数 |
conflicts |
|
temp_files |
磁盘临时文件数 |
temp_bytes |
磁盘临时文件大小 |
deadlocks |
死锁次数 |
blk_read_time |
IO读操作花费时间 |
blk_write_time |
IO写操作花费时间 |
blk_read_time/blk_write_time默认为空, 需要打开 track_io_time
参数, 可以使用 pg_test_timing
命令测试计时性能.
8.3. pg_stat_user_tables
显示各个表的活动.
列名 | 描述 |
---|---|
relid |
表id |
schemaname |
schema名 |
relname |
表名 |
seq_scan |
顺序扫描次数 |
seq_tup_read |
顺序扫描时元组读取个数 |
idx_scan |
索引使用次数 |
idx_tup_fetch |
索引元组返回个数 |
select schemaname, relname, seq_scan, seq_tup_read, seq_tup_read / seq_scan as avg, idx_scan
from pg_stat_user_tables
where seq_scan > 0
order by seq_tup_read desc
limit 25;
8.4. pg_stat_statements
select round((100 * total_time / sum(total_time) over ())::numeric, 2) AS percent,
round(total_time::numeric, 2) AS total,
calls,
round(mean_time::numeric, 2) AS mean,
query
from pg_stat_statements
order by total_time desc
limit 10;
9. 体系结构
9.2. 物理结构
template0和template1属于数据库模板, 区别是template1可以修改, template0只读.
9.2.1. OID
对象标识符,无符号4字节整数.所有的数据库对象由各自的OID管理
-
数据库对象OID保存在
pg_database
系统表里. -
表/索引/序列等对象OID保存在
pg_class
系统表里.
9.2.2. 表数据文件结构
-
pd_lower
: 指向free space开始位置 -
pd_upper
: 指向free space结束位置 -
如果Tuple超过page 1/4, 则会放到
TOAST
page中. -
Tuple可以使用
TID<pageNumber, offset>
二元组定位-
pageNumber: page序号.
-
offset: 指向第几个line pointer.
-
9.4. 内存结构
-
本地内存
-
work_mem: ORDER BY/DISTINCT会用到
-
maintenance_work_mem: VACUUM/REINDEX/CREATE INDEX会用到
-
temp_buffers: 临时表操作会用到
-
-
共享内存
-
shared buffer pool: 将表/索引文件载入内存
-
WAL buffer: WAL文件持久化缓冲区
-
CommitLog buffer: commit log中保存事务的状态,保存在缓冲区
-
10. 事务
PostgreSQL中每个SQL默认都是在一个事务中.
10.1. 事务语法
10.1.1. 开启事务
Command: BEGIN
Description: start a transaction block
Syntax:
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
where transaction_mode is one of:
ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
READ WRITE | READ ONLY
[ NOT ] DEFERRABLE
10.1.2. 完成事务
Command: COMMIT
Description: commit the current transaction
Syntax:
COMMIT [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
-
commit and chain: 复用上一个事务的设置.
-
如果事务过程中出错, 所有后续的SQL将直接报错不会执行, commit也会视为rollback处理.
10.1.3. 回滚事务
Command: ROLLBACK
Description: abort the current transaction
Syntax:
ROLLBACK [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
10.1.4. 设置savepoint
Command: SAVEPOINT
Description: define a new savepoint within the current transaction
Syntax:
SAVEPOINT savepoint_name
事务完成后会自动释放savepoint.
10.1.5. 手动释放savepoint
Command: RELEASE SAVEPOINT
Description: release a previously defined savepoint
Syntax:
RELEASE [ SAVEPOINT ] savepoint_name
10.2. 事务隔离级别
create table tbl_mvcc
(
id bigserial primary key,
ival integer
);
insert into tbl_mvcc(ival) values (1);
10.2.1. 脏读
一个事务看到了另外一个事务未提交的数据. (PostgreSQL下不可复现)
console1 | console2 |
---|---|
|
|
|
|
|
10.2.2. 不可重复读
一个事务查询结果与第一次的结果不同.(受到其他已提交事务 UPDATE 的影响)
console1 | console2 |
---|---|
|
|
|
|
|
10.2.3. 幻读
一个事务两次查询的结果集数量不一致.(受到其他已提交事务 INSERT/DELETE 的影响)
console1 | console2 |
---|---|
|
|
|
|
|
console1 | console2 |
---|---|
|
|
|
|
|
隔离级别 | 脏读 | 不可重复读 | 幻读 | 序列化异常 |
---|---|---|---|---|
Read Committed (PostgreSQL默认) |
❎ |
✅ |
✅ |
✅ |
Repeatable Read (MySQL默认) |
❎ |
❎ |
❎ |
✅ |
Serializable |
❎ |
❎ |
❎ |
❎ |
10.2.4. 查看全局事务默认隔离级别
select name,setting from pg_settings where name='default_transaction_isolation';
10.2.5. 修改全局事务默认隔离级别
-
修改postgresql.conf的default_transaction_isolation参数
-
ALTER SYSTEM SET default_transaction_isolation TO 'REPEATABLE READ';
10.2.6. 查看当前会话事务默认隔离级别
-
SHOW transaction_isolation;
-
select current_setting('transaction_isolation');
10.2.7. 设置当前会话事务默认隔离级别
-
set session characteristics as transaction isolation level REPEATABLE READ
-
START|BEGIN TRANSACTION ISOLATION LEVEL READ UNCOMMITTED … END
11. 锁
11.1. 表锁
11.1.1. 语法
Command: LOCK
Description: lock a table
Syntax:
LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
where lockmode is one of:
ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE
| SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
11.1.2. 表锁冲突
ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE | |
---|---|---|---|---|---|---|---|---|
ACCESS SHARE |
x |
|||||||
ROW SHARE |
x |
x |
||||||
ROW EXCLUSIVE |
x |
x |
x |
x |
||||
SHARE UPDATE EXCLUSIVE |
x |
x |
x |
x |
x |
|||
SHARE |
x |
x |
x |
x |
x |
x |
||
SHARE ROW EXCLUSIVE |
x |
x |
x |
x |
x |
x |
||
EXCLUSIVE |
x |
x |
x |
x |
x |
x |
x |
|
ACCESS EXCLUSIVE |
x |
x |
x |
x |
x |
x |
x |
x |
12. 分区
将一个表根据不同的规则分成多个块的行为, 称为分区, 每一个分区称为分区表.
-
应用了分区规则的列会自动添加not null的约束.
-
如果插入的值根据规则找不到匹配的分区, 则会报错.
-
PostgreSQL 10之后才内置分区功能, 支持Range和List分区, 11之后支持Hash分区.
12.2. 分区方式
-
Range分区
根据某一列值的范围插入相应的分区表, 比如根据日期范围分区, 仅支持单个列.
-
List分区
根据每个分区表的某一列值的集合分区. 支持多列/多表达式
-
Hash分区
根据某一列值的hash值分区
12.3. SQL
-- 创建主表
CREATE TABLE [ IF NOT EXISTS ] parent_table ( [
{ column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
] ) PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) }
-- 创建range型分区表
CREATE TABLE partition_table_name PARTITION OF parent_table FOR VALUES FROM (start) TO (end);
-- 创建list型分区表
CREATE TABLE partition_table_name PARTITION OF parent_table FOR VALUES IN (val1, val2) ;
-- 创建hash型分区表
CREATE TABLE partition_table_name PARTITION OF parent_table FOR VALUES WITH (MODULUS 4, REMAINDER 3);
-- 删除分区关系
ALTER TABLE parent_table ATTACH PARTITION partition_table_name
update语句违反了当前分区键的约束会报错 |
13. 清除WAL日志
pg_archivecleanup -d <archive_location> <oldest_kept_walfile>
如: pg_archivecleanup -d /var/lib/postgresql/data/pg_wal 000000010000000000000036
会将 000000010000000000000001~000000010000000000000035所有文件删除
pg_archivecleanup -d . `ls -r | head -2 | tail -1`
|
14. 查询优化
14.2. 物理优化
通过代价估算的方式挑选代价比较低的物理路径
15. pgbench
pgbench
命令是PostgreSQL自带的性能测试工具, 用于批量生产测试数据以及SQL性能测试.
默认测试数据集由4张表组成, 可以通过 -s
参数设置数据量倍数, 默认数据量如下
表名 | 数据量 |
---|---|
pgbench_branches |
1 |
pgbench_tellers |
10 |
pgbench_accounts |
100000 |
pgbench_history |
0 |
15.1. 初始化数据集
pgbench -i -I dtgvpf -q -s 1000 benchtest
-
-i
: 表明要进行数据初始化. -
-I
: 设置初始化步骤:-
d: 删除已经存在的测试表.
-
t: 创建测试表.
-
g: 生成测试数据.
-
v: 执行
VACUUM
. -
p: 创建主键.
-
f: 创建外键.
-
-
-q
: 每5秒数据输出一次进度, 否则每生成10万条数据输出一次. -
-s
: 设置测试数据量倍数, 如100则表示pgbench_accounts
里会生成1000万条数据. -
benchtest
: 用于测试的数据库名, 示例中库名为benchtest
.
15.2. SQL性能测试
pgbench -b tpcb-like -c 100 -C -j 100 -M simple -v -P 5 -r -T 30 benchtest
-
-b
: 运行内置脚本, 如果为自定义脚本, 替换为-f xxx.sql
参数.-
tpcb-like: 执行一个事务块, 包括3条update, 1条select和1条insert语句.
-
simple-update: 只执行3条update语句.
-
select-only: 只执行1条select语句.
-
-
-c
: 测试时建立的连接数量, 默认为1. -
-C
: 标识每次执行测试SQL时重新建立连接. -
-j
: pgbench线程数量. -
-M
: SQL模式: simple/extended/prepared. -
-v
: 标识测试前vacuumpgbench_tellers
和pgbench_branches
表, 并truncatepgbench_history
表. -
-P
: 设置每隔几秒输出一次测试进度. -
-r
: 标识输出SQL平均执行耗时. -
-T
: 设置测试执行时间. -
-R
: 设置测试每秒发送事务数. -
benchtest
: 用于测试的数据库名, 示例中库名为benchtest
.
16. 参考配置
# 固定参数
listen_addresses = '*'
superuser_reserved_connections = 10
unix_socket_directories = '., /tmp'
unix_socket_permissions = 0700
tcp_keepalives_idle = 60
tcp_keepalives_interval = 10
tcp_keepalives_count = 10
huge_pages = try
dynamic_shared_memory_type = posix
vacuum_cost_delay = 0
vacuum_cost_limit = 10000
bgwriter_delay = 10ms
bgwriter_lru_maxpages = 1000
bgwriter_lru_multiplier = 10.0
bgwriter_flush_after = 512kB
effective_io_concurrency = 0
max_worker_processes = 256
parallel_leader_participation = on
old_snapshot_threshold = 6h
wal_level = replica
synchronous_commit = off
full_page_writes = on
wal_compression = on
wal_buffers = 16MB
wal_writer_delay = 10ms
wal_writer_flush_after = 1MB
checkpoint_timeout = 30min
checkpoint_completion_target = 0.2
checkpoint_flush_after = 256kB
archive_mode = on
archive_command = '/bin/date'
max_wal_senders = 64
max_replication_slots = 64
hot_standby = on
max_standby_archive_delay = 120s
max_standby_streaming_delay = 120s
wal_receiver_status_interval = 1s
hot_standby_feedback = off
max_logical_replication_workers = 64
enable_partitionwise_join = on
enable_partitionwise_aggregate = on
random_page_cost = 1.1
log_destination = 'csvlog'
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%a.log'
log_truncate_on_rotation = on
log_rotation_age = 1d
log_rotation_size = 1GB
log_min_duration_statement = 5s
log_checkpoints = on
log_connections = off
log_disconnections = off
log_error_verbosity = verbose
log_lock_waits = on
log_statement = 'ddl'
log_temp_files = 256MB
track_io_timing = on
track_functions = pl
autovacuum = on
log_autovacuum_min_duration = 0
autovacuum_vacuum_scale_factor = 0.02
autovacuum_analyze_scale_factor = 0.01
autovacuum_freeze_max_age = 1200000000
autovacuum_multixact_freeze_max_age = 1250000000
autovacuum_vacuum_cost_delay = 0ms
idle_in_transaction_session_timeout = '6h'
vacuum_freeze_table_age = 200000000
vacuum_multixact_freeze_table_age = 200000000
default_text_search_config = 'pg_catalog.english'
shared_preload_libraries = 'pg_stat_statements'
deadlock_timeout = 1s
log_timezone = 'PRC'
datestyle = 'iso, mdy'
timezone = 'PRC'
lc_messages = 'C'
lc_monetary = 'C'
lc_numeric = 'C'
lc_time = 'C'
# 动态参数(以16C64G为例)
max_connections = 3200 # 物理内存(GB)*1000*(1/4)/5
# 共享内存, 读取数据后缓存在此处
shared_buffers = 16GB # IF use hugepage: 主机内存*(1/4) ELSE: min(32GB, 主机内存*(1/4))
max_prepared_transactions = 3200 # max_prepared_transactions=max_connections
# 单个SQL用于排序, HASH JOIN的内存区域
work_mem = 16MB # max(min(物理内存/4096, 64MB), 4MB)
maintenance_work_mem = 1GB # min( 8G, (主机内存*1/8)/max_parallel_maintenance_workers )
autovacuum_work_mem = 1GB # min( 8G, (主机内存*1/8)/autovacuum_max_workers )
max_parallel_maintenance_workers = 8 # min( max(2, CPU核数/2) , 16 )
max_parallel_workers_per_gather = 12 # min( max(2, CPU核数-4) , 24 )
max_parallel_workers = 12 # max(2, CPU核数-4)
max_wal_size = 32GB # shared_buffers*2
min_wal_size = 8GB # shared_buffers/2
max_sync_workers_per_subscription = 12 # min ( 32 , max(2, CPU核数-4) )
effective_cache_size = 32GB # 主机内存/2
autovacuum_max_workers = 8 # max(min( 8 , CPU核数/2 ) , 5)