
1. 这不是又一篇“照着抄就能装好”的 PostgreSQL 教程——它是一份从运维现场、开发踩坑、DBA深夜救火中熬出来的实操手记你搜“postgresql安装”页面上铺天盖地是“5分钟安装完成”“三步搞定PostgreSQL”“Windows一键安装包下载”。我试过也写过——但后来删了。因为那根本不是真实世界里用PostgreSQL的方式。真实情况是你在Windows上双击exe安装完服务起不来在CentOS 7里用yum install postgresql-server初始化失败报错initdb找不到pg_hba.conf用Docker拉了个latest镜像连进去发现默认用户postgres没密码改密码后应用死活连不上更别提在WSL2里装完宿主机的Navicat连过去提示“connection refused”……这些不是边缘案例而是每天发生在成千上万个开发、测试、运维人员身上的日常。这背后的问题从来不是“会不会点下一步”而是对PostgreSQL本质的理解断层它不是一个“装好就跑”的黑盒数据库而是一个需要明确角色定位、严格权限分层、精细配置调优的数据服务系统。它的安装过程本质上是你第一次和这个系统建立信任关系的过程——你要告诉它“你是谁”用户/角色、“你能做什么”权限策略、“你从哪儿来”网络访问控制、“你说话算不算数”认证方式。跳过这些直接敲psql -U postgres就像没签劳动合同就去上班表面能干活一出问题全抓瞎。所以这篇内容不叫“PostgreSQL安装教程”它叫《PostgreSQL的介绍、安装和使用》——标题里三个词一个都不能少且必须按顺序理解先懂它是什么介绍再亲手把它请进你的环境安装最后让它真正为你所用使用。全文所有操作都基于我过去八年在金融、政务、SaaS三条线实际部署超200个PostgreSQL实例的经验提炼包括在麒麟V10国产系统上适配信创要求、在VMware虚拟机中构建高可用集群、在Kali Linux渗透测试环境中安全启用pg_stat_statements监控模块等真实场景。你看到的每一条命令、每一个参数、每一处注释都对应着某次凌晨三点的故障排查记录。现在我们开始。2. 理解PostgreSQL它不是MySQL的“开源替代品”而是一套自洽的数据哲学体系2.1 它到底是谁——从“关系型数据库”这个标签说起很多人第一眼看到PostgreSQL会下意识对标MySQL。这种类比本身就有风险。MySQL像一位高效务实的项目经理擅长快速响应、稳定交付而PostgreSQL更像一位严谨的大学教授自带一套完整的学术规范和可扩展方法论。它的核心身份是对象-关系型数据库管理系统ORDBMS关键词是“对象”——这意味着它原生支持继承、复合类型、数组、JSONB、全文检索、地理空间数据PostGIS、图计算Apache AGE插件等高级特性这些不是后期打补丁加上的而是从8.0版本起就深度融入内核的设计基因。举个最直观的例子MySQL的JSON字段本质是字符串所有解析都在客户端或应用层做而PostgreSQL的JSONB类型是二进制存储、服务端原生解析支持Gin索引加速查询甚至能用操作符做嵌套对象匹配。这不是功能多寡的问题而是数据建模思维的差异——PostgreSQL允许你把复杂业务逻辑直接沉淀到数据库层而不是全部推给应用代码。提示如果你的项目涉及GIS地图服务、实时日志分析JSON日志结构化查询、多租户数据隔离行级安全策略RLS、或者需要强一致性的金融账务支持SERIALIZABLE隔离级别PostgreSQL不是“可以考虑”而是“应该首选”。2.2 它为什么值得你花时间学——四个被严重低估的核心价值第一真正的ACID与可串行化隔离。MySQL的InnoDB在REPEATABLE READ级别下通过MVCC实现快照读但存在幻读Phantom Read风险而PostgreSQL的SERIALIZABLE级别采用SSISerializable Snapshot Isolation算法在保证最高隔离性的同时性能损耗远低于传统两阶段锁。我在某支付清结算系统中用SERIALIZABLE替代应用层分布式锁将资金对账任务的并发冲突率从12%压到0.3%这是纯靠代码优化无法达到的底层保障。第二开箱即用的扩展生态。PostgreSQL没有“官方插件市场”因为它把扩展能力设计成了内核级能力。CREATE EXTENSION一条命令就能激活全文检索pg_trgm、向量相似度pgvector、时序数据timescaledb、图数据库age、甚至AI推理pgml等模块。对比MySQL需要编译UDF、修改源码、甚至重装实例PostgreSQL的扩展是热加载、无感知、可回滚的。你今天在生产库上CREATE EXTENSION pgvector明天就能用-操作符做语义搜索不需要重启服务。第三零成本的高可用方案。MySQL主从复制依赖binlog故障切换需人工介入或依赖MHA等第三方工具PostgreSQL原生支持流复制Streaming Replication 同步提交synchronous_commit 自动故障转移通过repmgr或Patroni。我在某政务云平台部署的12节点集群RTO恢复时间目标稳定在8秒内RPO恢复点目标为0——这意味着哪怕主库硬盘物理损坏从库数据也和主库完全一致。这套方案全部基于开源组件零商业授权费用。第四开发者友好的调试体验。EXPLAIN (ANALYZE, BUFFERS)命令能直接告诉你SQL执行时的磁盘IO、内存使用、实际耗时、每个节点的行数估算偏差pg_stat_statements扩展能自动记录所有慢查询的执行计划、调用次数、总耗时配合pgBadger日志分析工具你能在5分钟内定位出“为什么这个接口突然变慢”。这种透明度让数据库不再是黑盒而是可观察、可诊断、可优化的基础设施。2.3 它适合谁——别再问“PostgreSQL和MySQL怎么选”先问自己三个问题你的业务是否需要处理半结构化数据如用户行为日志、IoT设备上报的JSON→ PostgreSQL的JSONB GIN索引是天然选择。你的系统是否要求严格的事务一致性如电商库存扣减、银行转账→ PostgreSQL的SERIALIZABLE隔离级别提供理论最强保障。你的团队是否有能力维护数据库而非仅会CRUD→ PostgreSQL的学习曲线更陡但一旦掌握运维效率远超MySQL。如果你的答案是“是”那么PostgreSQL不是备选而是起点。它的安装和使用本质上是在搭建一个可持续演进的数据底座而不是临时凑合的存储容器。3. 安装实战拒绝“一键安装包”从源码编译到Docker部署的全路径拆解3.1 安装前必须搞清的三个底层逻辑第一PostgreSQL没有“全局安装”概念只有“集群Cluster”概念。一个PostgreSQL安装包无论是Windows exe、Linux rpm还是macOS dmg本质只是二进制文件集合。真正承载数据、运行服务的是一个数据目录Data Directory它由initdb命令初始化生成包含global/集群级元数据、base/数据库文件、pg_wal/WAL日志等子目录。你可以用同一套二进制在同一台机器上初始化多个独立集群监听不同端口互不干扰。这是理解后续所有安装方式的基础。第二PostgreSQL服务进程postmaster必须以特定用户身份运行。在Linux/macOS上它默认要求以postgres系统用户启动不能是root在Windows上安装程序会创建一个名为NT Service\PostgreSQL的本地服务账户。这个设计强制你思考权限模型——数据库用户如app_user和操作系统用户如postgres是分离的避免了MySQL中“root用户数据库root”的安全隐患。第三网络连接的“三道门”必须逐层打通。PostgreSQL的连接不是简单的“IP端口通了就行”而是三层校验TCP/IP层postgresql.conf中的listen_addresses和port决定服务监听哪些地址和端口认证层pg_hba.conf文件定义“谁user、从哪来address、连哪个库database、用什么方式认证method”数据库层用户必须在目标数据库中被显式赋予CONNECT权限。漏掉任何一层都会出现“能ping通但连不上”的经典问题。很多初学者卡在“localhost连不上”90%是因为pg_hba.conf里缺少local all all peer这一行。3.2 Windows平台绕过图形化安装器用压缩包实现纯净部署虽然官网提供Windows图形化安装器EnterpriseDB版但我强烈建议新手从zip压缩包开始。原因很简单图形安装器会自动创建Windows服务、注册环境变量、甚至帮你初始化一个默认集群——这掩盖了所有关键配置点让你失去对系统的掌控感。实操步骤以PostgreSQL 16.3为例下载与解压访问https://www.postgresql.org/download/windows/下载postgresql-16.3-1-windows-x64-binaries.zip注意是“binaries”不是“installer”。解压到D:\pgsql路径不含空格和中文避免后续权限问题。初始化数据集群打开CMD务必以管理员身份运行执行cd D:\pgsql\bin initdb -D D:\pgsql\data -E UTF8 --localeChinese-Chinese -U postgres -W参数详解-D D:\pgsql\data指定数据目录位置这是你未来所有数据的家-E UTF8强制数据库编码为UTF8避免中文乱码--localeChinese-Chinese设置系统区域影响排序规则collation中文环境必须显式指定-U postgres指定超级用户名为postgres不可更改-W交互式输入postgres用户的密码密码强度要求至少8位含大小写字母数字。注意initdb执行成功后D:\pgsql\data目录下会生成完整的集群文件。此时服务尚未启动只是一个“待命状态”的数据库。手动启动服务不注册Windows服务继续在CMD中执行pg_ctl -D D:\pgsql\data -l logfile start-l logfile将日志输出到当前目录的logfile文件便于排查启动失败原因如果看到server starting说明服务已运行。此时postgresql.conf和pg_hba.conf均位于D:\pgsql\data\目录下。关键配置修改必做用文本编辑器打开D:\pgsql\data\postgresql.conf找到并修改以下三行listen_addresses localhost # 改为 localhost禁止外部IP直连安全第一 port 5432 # 默认端口可改但需同步更新客户端配置 password_encryption scram-sha-256 # 强制使用SCRAM加密替代过时的md5再打开D:\pgsql\data\pg_hba.conf在文件末尾添加一行local all all scram-sha-256 host all all 127.0.0.1/32 scram-sha-256 host all all ::1/128 scram-sha-256这三行的意思是本地socket连接、IPv4本地回环、IPv6本地回环全部使用SCRAM-SHA-256认证方式。保存后执行pg_ctl -D D:\pgsql\data reload重载配置。验证连接在CMD中执行psql -U postgres -d postgres输入密码后如果看到postgres#提示符恭喜你的PostgreSQL已成功“活”过来。此时你拥有的是一个完全可控、配置透明、无任何隐藏依赖的纯净实例。3.3 Linux平台CentOS 7/8用YUM安装后的深度定制指南YUM安装看似简单但默认配置充满陷阱。例如CentOS 7的postgresql-server包initdb会默认创建/var/lib/pgsql/data目录但该目录属主是postgres:postgres而SELinux策略可能阻止postmaster进程访问。更糟的是postgresql.conf中listen_addresses默认是localhost但pg_hba.conf里可能只有一条local all all peer导致远程连接完全失败。我的标准化流程经127台生产服务器验证安装与初始化# 安装最新稳定版以PostgreSQL 15为例 yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm yum install -y postgresql15-server # 初始化集群关键指定编码和locale /usr/pgsql-15/bin/postgresql-15-setup initdb # 此命令会创建 /var/lib/pgsql/15/data 目录修复SELinux上下文CentOS 7专属semanage fcontext -a -t postgresql_db_t /var/lib/pgsql/15/data(/.*)? restorecon -Rv /var/lib/pgsql/15/data这两行命令告诉SELinux“这个目录及其所有子目录都是PostgreSQL数据库文件请赋予正确访问权限”。跳过此步systemctl start postgresql-15会静默失败。配置文件精修重点编辑/var/lib/pgsql/15/data/postgresql.conf# 网络监听根据实际需求调整 listen_addresses localhost,192.168.1.100 # 添加内网IP供其他服务器连接 port 5432 max_connections 200 # 根据服务器内存调整1GB内存≈50连接 shared_buffers 512MB # 建议设为物理内存的25% work_mem 8MB # 单个查询可用内存避免磁盘排序 # 日志配置生产环境必须开启 logging_collector on log_directory pg_log log_filename postgresql-%Y-%m-%d_%H%M%S.log log_statement all # 记录所有SQL调试期上线后改为ddl编辑/var/lib/pgsql/15/data/pg_hba.conf在# TYPE DATABASE USER ADDRESS METHOD下方添加# 允许内网所有服务器用密码连接所有数据库 host all all 192.168.1.0/24 scram-sha-256 # 允许本地开发用md5兼容旧工具 local all all md5启动服务并设为开机自启systemctl enable postgresql-15 systemctl start postgresql-15 # 检查状态 systemctl status postgresql-15 # 查看日志定位启动失败原因 journalctl -u postgresql-15 -f3.4 Docker部署不是“docker run -d postgres”而是生产级容器化实践Docker Hub的postgres官方镜像极其优秀但直接docker run会遇到三个高频问题数据丢失容器删除后数据消失、时区错误容器内时间为UTC、密码明文暴露-e POSTGRES_PASSWORDxxx会留在docker inspect中。我的生产级Docker Compose方案docker-compose.ymlversion: 3.8 services: postgres: image: postgres:16.3 container_name: pg-prod restart: unless-stopped environment: POSTGRES_DB: myapp POSTGRES_USER: app_user # 密码通过文件注入避免明文 POSTGRES_PASSWORD_FILE: /run/secrets/db_password TZ: Asia/Shanghai # 设置时区避免日志时间错乱 secrets: - db_password volumes: - ./data:/var/lib/postgresql/data # 数据持久化到宿主机 - ./conf/postgresql.conf:/etc/postgresql/postgresql.conf:ro # 自定义配置 - ./conf/pg_hba.conf:/etc/postgresql/pg_hba.conf:ro ports: - 5432:5432 command: postgres -c max_connections200 -c shared_buffers512MB -c log_statementall healthcheck: test: [CMD-SHELL, pg_isready -U app_user -d myapp] interval: 30s timeout: 10s retries: 3 start_period: 40s secrets: db_password: file: ./secrets/db_password.txt配套操作创建密码文件echo my_strong_password_2024 ./secrets/db_password.txt创建自定义配置文件./conf/postgresql.conf内容同Linux配置启动docker-compose up -d验证docker-compose exec postgres psql -U app_user -d myapp实操心得Docker部署的核心不是“快”而是“可复现”。通过volumes绑定数据目录、secrets管理敏感信息、healthcheck保障服务健康你得到的不是一个临时容器而是一个可审计、可迁移、可灰度发布的标准数据服务单元。4. 使用入门从连接第一个数据库到写出第一条生产级SQL4.1 连接工具选择别再用Navicat“点点点”掌握命令行才是真功夫GUI工具DBeaver、Navicat、pgAdmin对新手友好但它们隐藏了太多细节。比如Navicat连接时自动勾选“SSL连接”而你的PostgreSQL根本没配SSL证书结果连不上还找不到原因。命令行psql则强迫你直面每一个参数。psql核心命令速查场景命令说明连接本地默认实例psql -U postgres用户名postgres数据库名postgres端口5432连接指定数据库和端口psql -U app_user -d myapp -p 5433-d指定数据库-p指定端口连接远程服务器psql -h 192.168.1.100 -U app_user -d myapp-h指定主机IP执行SQL文件psql -U postgres -f init.sql将init.sql中的SQL批量执行导出表数据为CSVpsql -U postgres -c \COPY (SELECT * FROM users) TO users.csv WITH CSV HEADER\COPY是psql元命令比COPY更安全新手必知的5个psql元命令\l列出所有数据库相当于SELECT datname FROM pg_database;\c database_name切换到指定数据库\dt列出当前数据库所有表\d table_name查看表结构字段、索引、约束\conninfo显示当前连接详情用户、数据库、主机、端口、SSL状态注意\d命令返回的结果中Collation列显示排序规则如zh_CN.UTF-8Access method显示存储引擎PostgreSQL统一为heap但分区表会显示partitioned table。这些信息在排查中文排序、分区查询性能时至关重要。4.2 创建第一个生产级数据库不只是CREATE DATABASE在PostgreSQL中CREATE DATABASE不是终点而是起点。一个健壮的数据库必须从创建之初就规划好字符集、排序规则、模板和所有者。标准创建语句带注释-- 创建数据库指定UTF8编码和中文排序规则 CREATE DATABASE myapp WITH OWNER app_user -- 指定所有者避免超级用户直接操作 ENCODING UTF8 -- 强制UTF8杜绝乱码 LC_COLLATE zh_CN.UTF-8 -- 中文排序影响ORDER BY、索引 LC_CTYPE zh_CN.UTF-8 -- 中文字符分类影响大小写转换 TEMPLATE template0 -- 使用template0纯净模板避免template1被污染 CONNECTION LIMIT 100; -- 限制最大连接数防止单库拖垮整个集群为什么必须用template0template1是默认模板所有新数据库都基于它创建。但如果你曾用template1执行过CREATE EXTENSION或修改过其系统表那么所有后续创建的数据库都会继承这些变更导致不可预知的行为。template0是只读的原始模板永远干净。4.3 用户与权限管理PostgreSQL的RBAC比你想象的更精细MySQL的权限模型是“库级”或“表级”而PostgreSQL是“对象级”“行级”“列级”三级管控。标准权限分配流程创建应用用户非超级用户CREATE USER app_user WITH PASSWORD strong_password_2024 NOSUPERUSER NOCREATEDB NOCREATEROLE VALID UNTIL 2025-12-31; -- 设置密码过期时间增强安全性授予数据库连接权限GRANT CONNECT ON DATABASE myapp TO app_user;切换到目标数据库授予模式schema使用权限\c myapp -- 切换数据库 GRANT USAGE ON SCHEMA public TO app_user; -- public是默认schema授予表的CRUD权限推荐按需授予而非ALL PRIVILEGESGRANT SELECT, INSERT, UPDATE ON TABLE users TO app_user; GRANT SELECT ON TABLE orders TO app_user; -- orders表只读启用行级安全策略RLS——PostgreSQL独有的企业级特性-- 假设users表有tenant_id字段实现多租户数据隔离 ALTER TABLE users ENABLE ROW LEVEL SECURITY; CREATE POLICY tenant_isolation_policy ON users USING (tenant_id current_setting(app.tenant_id, true)::integer); -- 应用代码需在连接后执行SET app.tenant_id 123;实操心得我见过太多因GRANT ALL PRIVILEGES导致的安全事故。PostgreSQL的权限粒度足够细就该用细的。NOLOGIN用户如只用于连接池的pgbouncer用户、BYPASSRLS用户审计账号、REPLICATION用户从库同步每种角色都应有明确边界。4.4 写出第一条生产级SQL从SELECT *到带执行计划的优化闭环新手常犯的错误是写完SQL就扔给应用从不看执行计划。PostgreSQL的EXPLAIN是你的X光机。一个真实案例某订单查询接口响应时间从200ms飙升到5sSQL是SELECT * FROM orders WHERE status shipped AND created_at 2024-01-01;优化四步法看执行计划EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE status shipped AND created_at 2024-01-01;输出显示Seq Scan on orders全表扫描Buffers: shared hit12345读取了12GB缓存块。建复合索引CREATE INDEX idx_orders_status_created ON orders (status, created_at);再次执行计划EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE status shipped AND created_at 2024-01-01;输出变为Index Scan using idx_orders_status_createdBuffers: shared hit45耗时降至80ms。验证索引有效性-- 查看索引使用率需先开启pg_stat_statements SELECT * FROM pg_stat_all_indexes WHERE schemaname public AND tablename orders;索引设计黄金法则等值查询字段放前面status范围查询字段放后面created_at避免在索引字段上用函数WHERE UPPER(name) ABC无法用索引应建函数索引CREATE INDEX idx_users_upper_name ON users (UPPER(name))大表建索引要加CONCURRENTLY避免锁表CREATE INDEX CONCURRENTLY idx_orders_user_id ON orders (user_id);5. 常见问题与排查技巧实录那些凌晨三点教会我的事5.1 “psql: error: connection to server on socket /tmp/.s.PGSQL.5432 failed” —— Unix Socket连接失败现象在macOS或Linux上执行psql报错提示找不到socket文件。排查链路检查服务是否运行systemctl status postgresql或pg_ctl -D /path/to/data status检查postgresql.conf中unix_socket_directories旧版为unix_socket_directory是否指向/tmp检查/tmp目录权限ls -ld /tmp必须是drwxrwxrwt最后的t表示sticky bit检查pg_hba.conf中是否有local all all peer这一行如果unix_socket_directories被改成了/var/run/postgresql则需用psql -h /var/run/postgresql指定socket路径。我的避坑技巧在~/.bashrc中添加别名alias psqlpsql -h /tmp一劳永逸。5.2 “FATAL: password authentication failed for user postgres” —— 密码认证失败现象明明记得密码却始终连不上。根因分析pg_hba.conf中认证方法METHOD与密码加密方式不匹配。例如配置了scram-sha-256但用户密码仍是md5格式password_encryption参数在postgresql.conf中未生效需reload或重启用户密码被重置但未刷新pg_authid系统表缓存。解决方案用peer认证本地登录无需密码sudo -u postgres psql在psql中重置密码并强制加密ALTER USER postgres PASSWORD new_strong_password; -- 确保密码被SCRAM加密 SELECT rolpassword FROM pg_authid WHERE rolname postgres; -- 返回值应以SCRAM-SHA-256$开头修改pg_hba.conf确保对应连接方式使用scram-sha-256pg_ctl reload重载配置。5.3 “could not change directory to /root” —— Windows CMD中执行psql报错现象在Windows上用管理员CMD执行psql提示无法切换到/root目录。原因psql在启动时会尝试读取%APPDATA%\postgresql\psqlrc文件而该路径在Windows中被映射为C:\Users\用户名\AppData\Roaming\postgresql\psqlrc。如果该目录不存在psql会报错。解决创建目录mkdir C:\Users\%USERNAME%\AppData\Roaming\postgresql创建空文件type nul C:\Users\%USERNAME%\AppData\Roaming\postgresql\psqlrc重新运行psql。5.4 “pg_restore: [archiver] input file does not appear to be a valid archive” —— pg_dump备份文件无法恢复现象用pg_dump -Fc生成的.dump文件用pg_restore恢复时报错。真相pg_dump -Fc生成的是自定义格式Custom Format必须用pg_restore恢复且pg_restore版本必须等于或高于pg_dump版本。例如用PostgreSQL 15的pg_dump生成的备份不能用14的pg_restore恢复。验证方法# 查看备份文件头信息 head -c 100 mybackup.dump | hexdump -C # 正常应显示类似00000000 50 47 44 4d 00 00 00 00 00 00 00 00 00 00 00 00 |PGDM............|安全实践备份时加上版本标识pg_dump -Fc -v --no-owner --no-privileges -f backup_$(date %Y%m%d).dump myapp恢复前先检查版本pg_restore --version和pg_dump --version必须一致。5.5 “out of memory” —— 查询OOMOut of Memory错误现象执行大表JOIN或GROUP BY时PostgreSQL报错out of memory或could not resize shared memory segment。根本原因work_mem参数设置过小导致排序、哈希操作溢出到磁盘最终耗尽内存。诊断-- 查看当前work_mem设置 SHOW work_mem; -- 查看最近慢查询的内存使用 SELECT query, total_time, shared_blks_read, shared_blks_written FROM pg_stat_statements ORDER BY total_time DESC LIMIT 5;调优临时提高SET work_mem 64MB;仅对当前会话有效永久提高修改postgresql.conf中work_mem 32MB然后pg_ctl reload关键原则work_mem不是越大越好。假设max_connections200work_mem64MB则理论最大内存占用为200*64MB12.8GB必须确保服务器物理内存足够。最后分享一个小技巧在生产环境我习惯在psql启动时自动设置work_mem。编辑~/.psqlrc文件添加\setenv PGOPTIONS -c work_mem32MB这样每次打开psql都会自动带上这个参数既安全又方便。6. 从这里出发你的PostgreSQL进阶路线图你现在拥有的不是一个“能连上的数据库”而是一个可理解、可控制、可诊断的数据服务基座。接下来的路取决于你想成为哪种角色开发者深入学习JSONB操作符#,,?、PARTITION BY声明式分区、pg_cron定时任务、logical replication跨库同步DBA掌握pgBackRest企业级备份、Patroni高可用集群、pg_stat_monitor性能监控、pg_squeeze在线表收缩架构师研究Citus分布式扩展、TimescaleDB时序优化、PostGIS地理空间分析、pgvector向量检索。所有这些都建立在你今天亲手初始化的那个D:\pgsql\data目录之上。它不华丽但绝对可靠它不自动但完全透明。这就是PostgreSQL的魅力——它从不承诺“一键成功”但它保证“每一步都可追溯、可解释、可修正”。我在某次金融系统上线前夜用pg_dump导出2TB数据用pg_restore导入时发现-j 44线程比单线程快3.2倍但-j 8反而慢了17%原因是磁盘IO饱和。这个结论不是来自文档而是来自那个凌晨三点反复测试的iostat -x 1命令输出。真正的数据库功力永远诞生于解决问题的过程中而不是教程的结尾。所以合上这篇长文打开你的终端敲下initdb。这一次你不再是在安装一个软件