Article

关系型数据库PostgreSQL

更新于:2026-07-16

第一章:PostgreSQL 简介与安装

1.1 PostgreSQL 概述

概念名称说明注意事项
PostgreSQL开源对象-关系型数据库系统,支持 SQL 标准、扩展性强、ACID 兼容不是 MySQL 的分支,而是独立发展的数据库项目
ACID 特性原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)PostgreSQL 默认事务隔离级别为 READ COMMITTED
MVCC多版本并发控制,允许多个事务同时读写而不阻塞避免了读写锁,但需定期 VACUUM 清理旧版本
扩展机制支持通过 CREATE EXTENSION 添加功能(如 PostGIS、uuid-ossp)扩展需预先安装到系统或通过包管理器提供
社区与生态由全球开发者社区维护,无商业公司主导企业可选择 EDB(EnterpriseDB)等提供商业支持

1.2 安装 PostgreSQL(Linux / Windows / macOS)

步骤名称操作细节注意事项
Linux (Ubuntu/Debian) 安装sudo apt update && sudo apt install postgresql postgresql-contrib安装后自动创建 postgres 用户和默认集群
Linux (RHEL/CentOS) 安装sudo dnf install postgresql-server postgresql-contrib(或 yum)需启用并启动服务:sudo systemctl enable --now postgresql;然后运行 sudo postgresql-setup --initdb
Windows 安装从官网 https://www.postgresql.org/download/windows/ 下载图形化安装程序(如 EDB installer)安装过程中会设置超级用户密码和端口(默认 5432)
macOS 安装(Homebrew)brew install postgresql安装后需手动初始化:initdb /opt/homebrew/var/postgres(Apple Silicon 路径)
验证安装终端执行 psql --versionpg_config --version若命令未找到,需检查 PATH 或使用完整路径(如 /usr/lib/postgresql/16/bin/psql

1.3 初始化数据库集群

操作名称操作细节注意事项
initdb 命令initdb -D /path/to/data/directory必须由 postgres 用户或具有写权限的用户执行;例如:sudo -u postgres initdb -D /var/lib/postgresql/16/main
指定编码与区域initdb -D /data --encoding=UTF8 --locale=en_US.UTF-8推荐使用 UTF8 编码,避免后续字符集问题
数据目录结构包含 base/(数据库文件)、global/(全局表)、pg_wal/(WAL 日志)、postgresql.confpg_hba.conf不要手动修改数据目录内文件,除非明确知道后果
重复初始化风险若目标目录非空,initdb 会拒绝执行需先清空目录或指定新路径
自动初始化某些发行版(如 Ubuntu)在安装包时自动调用 initdb 创建默认集群可通过 pg_lsclusters 查看已存在集群

1.4 启动与停止服务

操作名称操作细节注意事项
使用 systemctl(Linux)启动:sudo systemctl start postgresql;停止:sudo systemctl stop postgresql;状态:sudo systemctl status postgresql服务名可能带版本号,如 postgresql@16-main
使用 pg_ctl(通用)启动:pg_ctl -D /data/dir start;停止:pg_ctl -D /data/dir stop -m fast;重启:pg_ctl -D /data/dir restart-m 模式:smart(默认)、fast、immediate;immediate 会中断所有连接
Windows 服务管理通过”服务”管理器启动/停止 PostgreSQL 服务,或使用 net start postgresql-x64-16服务名取决于安装时指定的版本和位数
检查端口监听ss -tulnp | grep 5432lsof -i :5432若未监听,检查 postgresql.conflisten_addressesport
自动启动配置Linux:sudo systemctl enable postgresql;Windows:安装时默认设为自动启动禁用自动启动:sudo systemctl disable postgresql

第二章:命令行工具基础

2.1 psql 命令行客户端入门

方法/命令名称语法/说明用途代码示例注意事项
启动 psql(默认连接)psql以当前系统用户身份连接同名数据库psql需存在同名数据库和用户;通常需先切换到 postgres 用户
指定数据库连接psql -d dbname连接指定数据库psql -d mydb若用户未指定,默认使用当前系统用户名
指定用户连接psql -U username -d dbname以指定用户身份连接数据库psql -U alice -d mydb可能提示输入密码,取决于 pg_hba.conf 配置
退出 psql\qCtrl+D退出 psql 会话\q不会提交未完成的事务,如有 BEGIN 未 COMMIT 会被回滚
显示帮助\?查看 psql 元命令帮助\?与 SQL 帮助 \h 不同,\? 是 psql 自身命令

2.2 连接数据库(本地与远程)

方法/命令名称语法/说明用途代码示例注意事项
本地 socket 连接psql -h /var/run/postgresql -d dbname使用 Unix 域套接字连接(Linux/macOS)psql -h /tmp -d postgres默认路径因发行版而异,Ubuntu 通常为 /var/run/postgresql
TCP/IP 本地连接psql -h localhost -p 5432 -U user -d dbname通过 TCP 连接本地实例psql -h 127.0.0.1 -p 5432 -U postgres -d testdb需确保 postgresql.conflisten_addresses 包含 localhost
远程连接psql -h remote_ip -p port -U user -d dbname连接远程 PostgreSQL 服务器psql -h 192.168.1.100 -p 5432 -U appuser -d appdb需配置:1. postgresql.conf: listen_addresses = '*';2. pg_hba.conf: 添加 host 记录;3. 防火墙开放端口
使用 .pgpass 文件免密~/.pgpass 中写入 host:port:database:username:password自动填充密码,避免交互输入192.168.1.100:5432:appdb:appuser:mypassword文件权限必须为 600(chmod 600 ~/.pgpass),否则被忽略
环境变量连接设置 PGHOST, PGPORT, PGDATABASE, PGUSER, PGPASSWORD通过环境变量指定连接参数export PGUSER=alice && psqlPGPASSWORD 存在安全风险,建议仅用于脚本且及时清除

2.3 常用 psql 元命令(\d, \l, \c 等)

元命令语法/说明用途代码示例注意事项
\l / \list列出所有数据库查看集群中所有数据库\l显示数据库名、所有者、编码、访问权限等
\c / \connect\c [dbname] [username] [host] [port]切换当前连接的数据库或用户\c mydb alice若省略参数,保持原值;可仅切换数据库:\c newdb
\d列出当前数据库中的表、视图、序列等快速浏览对象\d等价于 \dtvms(table, view, materialized view, sequence)
\dt列出所有表仅显示普通表\dt可加模式限定:\dt public.*
\d table_name显示表结构(列、类型、约束)查看表定义\d users显示主键、外键、默认值、是否为空等
\dv列出视图查看用户定义视图\dv不包括系统视图
\du列出角色/用户查看用户及其权限\du显示超级用户、创建 DB 权限等
\dn列出模式(schema)查看数据库中的 schema\dn默认有 public schema
\x切换扩展显示模式(横向/纵向)使宽表结果更易读\xSELECT * FROM large_table;再次执行 \x 可关闭;也可用 \x auto 自动切换
\timing开启/关闭 SQL 执行时间显示性能调试\timingSELECT count(*) FROM logs;显示毫秒级耗时

2.4 脚本执行与输出重定向

操作名称语法/说明用途代码示例注意事项
执行 SQL 脚本文件psql -f script.sql -d dbname批量运行 SQL 语句psql -U postgres -d mydb -f init.sql脚本中可用 \echo 输出信息
从标准输入执行cat script.sql | psql -d dbname管道方式执行echo "SELECT version();" | psql -d postgres适用于 shell 脚本中动态生成 SQL
输出查询结果到文件psql -d dbname -c "SQL" -o output.txt将结果保存为文件psql -d sales -c "SELECT * FROM orders;" -o orders.txt默认包含标题和边框;可用 -t(元组模式)去除
静默模式(无提示)psql -q -f script.sql抑制启动/结束消息psql -q -d test -f setup.sql适合自动化脚本,避免日志污染
设置输出格式使用 \pset 或命令行选项控制格式控制 CSV、对齐、分隔符等psql -d db -c "SELECT a,b FROM t;" --csv -o data.csv常用选项:--csv(CSV 格式)、-t(仅数据,无标题)、-A(非对齐模式)
错误处理(ON_ERROR_STOP)在脚本开头加 \set ON_ERROR_STOP on遇错立即退出\set ON_ERROR_STOP on\nCREATE TABLE ...默认 psql 遇错继续执行,可能掩盖问题
导出为 COPY 格式psql -d db -c "\copy (SELECT ...) TO 'file.csv' WITH CSV HEADER"客户端侧导出(无需 superuser)\copy (SELECT id,name FROM users) TO '/tmp/users.csv' WITH CSV HEADER\copy 是 psql 命令,不同于服务器端的 COPY

第三章:数据库与用户管理

3.1 创建与删除数据库

方法/命令名称语法/说明用途代码示例注意事项
CREATE DATABASECREATE DATABASE dbname [WITH [OWNER [=] user] [TEMPLATE [=] template] [ENCODING [=] encoding] ...];创建新数据库CREATE DATABASE myapp WITH OWNER = alice ENCODING = 'UTF8';需具有 CREATEDB 权限;不能在事务块中执行
DROP DATABASEDROP DATABASE [IF EXISTS] dbname;删除数据库DROP DATABASE IF EXISTS myapp;数据库必须为空(无连接);无法删除当前连接的数据库
使用模板创建指定 TEMPLATE 选项基于现有模板数据库克隆结构CREATE DATABASE testdb WITH TEMPLATE = template0;template0 是干净模板,template1 可能被修改过;避免使用非标准模板
查看数据库列表\l 或查询 pg_database列出所有数据库SELECT datname FROM pg_database;系统数据库包括 postgres、template0、template1
连接限制在 CREATE DATABASE 中指定 CONNECTION LIMIT n限制该数据库的最大并发连接数CREATE DATABASE limited_db CONNECTION LIMIT 5;超级用户不受此限制

3.2 用户与角色管理

方法/命令名称语法/说明用途代码示例注意事项
CREATE ROLECREATE ROLE name [WITH] option [...];创建角色(用户是带 LOGIN 的角色)CREATE ROLE alice WITH LOGIN PASSWORD 'secret123' CREATEDB;默认不带 LOGIN,仅为权限组;需显式指定 LOGIN 才可连接
CREATE USERCREATE USER name [WITH option];创建可登录用户(等价于 CREATE ROLE ... LOGINCREATE USER bob WITH PASSWORD 'pass';实际是 CREATE ROLE 的别名,官方推荐统一用 CREATE ROLE
ALTER ROLEALTER ROLE name [WITH] option;ALTER ROLE name RENAME TO newname;修改角色属性或重命名ALTER ROLE alice VALID UNTIL '2027-01-01';可修改密码、有效期、权限等;不能修改超级用户为非超级用户(除非自身是超级用户)
DROP ROLEDROP ROLE [IF EXISTS] name;删除角色DROP ROLE IF EXISTS bob;角色不能拥有任何对象(表、函数等),否则需先转移所有权或删除对象
查看角色列表\du 或查询 pg_roles列出所有角色及其属性SELECT rolname, rolsuper, rolcreatedb FROM pg_roles;包含系统角色(如 pg_signal_backend)
设置默认权限ALTER ROLE name SET parameter = value;为角色设置会话级 GUC 参数ALTER ROLE alice SET search_path TO myapp, public;影响该用户后续所有会话的默认行为

3.3 权限控制(GRANT / REVOKE)

方法/命令名称语法/说明用途代码示例注意事项
GRANT on DATABASEGRANT {CONNECT | CREATE | TEMPORARY} ON DATABASE db TO role;授予数据库级权限GRANT CONNECT, CREATE ON DATABASE myapp TO alice;默认 PUBLIC 有 CONNECT 和 TEMPORARY 权限;可 REVOKE PUBLIC 撤销
GRANT on SCHEMAGRANT {USAGE | CREATE} ON SCHEMA schema TO role;授予模式级权限GRANT USAGE ON SCHEMA public TO bob;USAGE 允许访问模式内对象;CREATE 允许在模式中建表
GRANT on TABLEGRANT {SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER} ON TABLE tbl TO role;授予表级 DML/DDL 权限GRANT SELECT, INSERT ON TABLE users TO app_role;可批量授权:GRANT SELECT ON ALL TABLES IN SCHEMA public TO role;
GRANT on SEQUENCEGRANT {USAGE | SELECT | UPDATE} ON SEQUENCE seq TO role;授予序列权限GRANT USAGE ON SEQUENCE user_id_seq TO app_role;SERIAL 类型自动创建序列,需单独授权
GRANT on FUNCTIONGRANT EXECUTE ON FUNCTION func(...) TO role;授予函数执行权限GRANT EXECUTE ON FUNCTION get_user(int) TO webuser;函数需指定完整参数签名
REVOKEREVOKE privilege ON object FROM role [CASCADE];撤销权限REVOKE INSERT ON TABLE logs FROM guest;默认 RESTRICT 模式,若权限被转授则失败;CASCADE 会级联撤销
查看权限查询 information_schema.table_privileges\dp tablename检查对象权限分配\dp users\dp 显示 ACL(访问控制列表),格式如 alice=arwdDxt/postgres

3.4 默认数据库与模板数据库

概念/操作名称说明用途代码示例注意事项
postgres 数据库安装后默认存在的数据库用于管理操作、工具连接、初始连接psql -U postgres -d postgres建议保留,不要删除;许多工具默认连接它
template0只读模板数据库,编码和区域固定作为干净模板创建新数据库CREATE DATABASE clean_db WITH TEMPLATE = template0;不可连接、不可修改;用于恢复标准环境
template1默认模板数据库,可被用户修改新数据库默认从此克隆CREATE DATABASE newdb;(等价于 WITH TEMPLATE template1若 template1 被污染(如安装了扩展),会影响所有新库
重置 template1用 template0 覆盖 template1修复被修改的默认模板DROP DATABASE template1; CREATE DATABASE template1 WITH TEMPLATE = template0;需先断开所有连接;操作需谨慎
自定义模板数据库任意数据库设为模板(datistemplate = true快速部署预配置环境UPDATE pg_database SET datistemplate = true WHERE datname = 'my_template';需超级用户权限;模板数据库不能被普通用户删除

第四章:SQL 基础操作

4.1 数据类型与表结构设计

数据类型名称语法/说明用途代码示例注意事项
INTEGER / INT4 字节整数,范围 -2147483648 到 +2147483647存储普通整数 ID、计数等user_id INTEGER可用 SERIAL 自动递增(实际是 INTEGER + 序列)
BIGINT8 字节整数存储大数值(如时间戳、海量计数)created_at BIGINT对应 SERIAL8(BIGSERIAL)
TEXT可变长字符串,无长度限制存储任意长度文本description TEXT比 VARCHAR 更灵活;性能差异在现代 PostgreSQL 中极小
VARCHAR(n)最大 n 字符的可变长字符串需限制长度的文本字段email VARCHAR(255)超长会报错;n=0 表示无限制(等同 TEXT)
CHAR(n)固定长度字符串,不足补空格兼容旧系统或固定码(如国家代码)country_code CHAR(2)一般不推荐,浪费存储且易引发比较问题
BOOLEANTRUE / FALSE / NULL存储逻辑标志is_active BOOLEAN可用 ‘t’/‘f’、1/0 等输入,但输出为 true/false
TIMESTAMP不带时区的时间戳记录事件发生时间(本地视角)login_time TIMESTAMP默认精度为微秒;可用 TIMESTAMP(0) 精确到秒
TIMESTAMPTZ带时区的时间戳存储 UTC 时间,自动转换客户端时区event_time TIMESTAMPTZ实际存储为 UTC;显示时按当前 timezone GUC 转换
DATE日期(年-月-日)仅需日期部分birth_date DATE支持日期运算(如 CURRENT_DATE + INTERVAL '1 day'
NUMERIC(p,s)任意精度十进制数金融、科学计算等需精确小数场景price NUMERIC(10,2)p=总位数,s=小数位;比 FLOAT8 更精确但稍慢
UUID128 位通用唯一标识符分布式系统主键id UUID PRIMARY KEY需启用扩展:CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; 生成:uuid_generate_v4()
JSONB二进制存储的 JSON,支持索引和查询存储半结构化数据metadata JSONB推荐用 JSONB 而非 JSON(后者为文本,无索引支持)

4.2 CREATE / ALTER / DROP TABLE

方法/命令名称语法/说明用途代码示例注意事项
CREATE TABLECREATE TABLE table_name (col type [constraints], ...);创建新表CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT NOT NULL);可加 IF NOT EXISTS 避免报错
主键约束PRIMARY KEY 或 UNIQUE NOT NULL定义唯一标识行id INTEGER PRIMARY KEY自动创建唯一索引
外键约束FOREIGN KEY (col) REFERENCES parent(col)建立表间引用关系user_id INTEGER REFERENCES users(id)被引用表必须有主键或唯一约束;默认 ON DELETE NO ACTION
默认值DEFAULT value插入时未指定则使用默认created_at TIMESTAMP DEFAULT NOW()可用函数(如 NOW())、常量或表达式
ALTER TABLE ADD COLUMNALTER TABLE tbl ADD COLUMN col type [DEFAULT val];增加新列ALTER TABLE users ADD COLUMN email TEXT;加带 DEFAULT 的列在大表上可能锁表(PG ≥11 优化)
ALTER TABLE DROP COLUMNALTER TABLE tbl DROP COLUMN col [CASCADE];删除列ALTER TABLE users DROP COLUMN temp_flag;CASCADE 会删除依赖该列的对象(如视图)
ALTER TABLE ALTER COLUMN TYPEALTER TABLE tbl ALTER COLUMN col TYPE new_type [USING expr];修改列数据类型ALTER TABLE logs ALTER COLUMN message TYPE TEXT;若类型不兼容,需提供 USING 表达式转换
DROP TABLEDROP TABLE [IF EXISTS] tbl [CASCADE];删除表及其数据DROP TABLE IF EXISTS temp_data;CASCADE 会删除依赖对象(如外键、视图);RESTRICT 为默认

4.3 INSERT / UPDATE / DELETE

方法/命令名称语法/说明用途代码示例注意事项
INSERT INTOINSERT INTO tbl (col1, col2) VALUES (val1, val2);插入单行或多行INSERT INTO users (name, email) VALUES ('Alice', 'a@example.com');可省略列名(需按表定义顺序提供所有值)
INSERT RETURNINGINSERT ... RETURNING * | cols;返回插入后的行INSERT INTO users (name) VALUES ('Bob') RETURNING id;常用于获取自增 ID 或完整记录
UPDATEUPDATE tbl SET col = val WHERE condition;修改符合条件的行UPDATE users SET email = 'new@a.com' WHERE id = 1;必须带 WHERE,否则更新全表!
UPDATE RETURNINGUPDATE ... RETURNING * | cols;返回更新后的行UPDATE users SET last_login = NOW() WHERE id = 1 RETURNING *;可用于审计或链式操作
DELETE FROMDELETE FROM tbl WHERE condition;删除符合条件的行DELETE FROM sessions WHERE expired < NOW();必须带 WHERE,否则清空整表!
DELETE RETURNINGDELETE ... RETURNING * | cols;返回被删除的行DELETE FROM logs WHERE created < '2020-01-01' RETURNING id;可用于归档前捕获数据
UPSERT (ON CONFLICT)INSERT ... ON CONFLICT (col) DO UPDATE SET ...插入或冲突时更新INSERT INTO users (id, name) VALUES (1, 'Alice') ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name;需目标列有唯一约束或索引;EXCLUDED 表示拟插入的值

4.4 SELECT 查询基础(WHERE, ORDER BY, LIMIT)

方法/命令名称语法/说明用途代码示例注意事项
SELECT 列SELECT col1, col2 FROM tbl;查询指定列SELECT name, email FROM users;可用 * 表示所有列(不推荐用于生产)
WHERE 条件WHERE expression过滤行SELECT * FROM users WHERE age >= 18;支持 AND/OR/NOT、IN、BETWEEN、LIKE、IS NULL 等
ORDER BYORDER BY col [ASC|DESC] [, col2 ...]排序结果SELECT * FROM products ORDER BY price DESC, name ASC;默认 ASC;NULL 值默认排最后(可用 NULLS FIRST/LAST 控制)
LIMIT / OFFSETLIMIT n [OFFSET m]分页或限制结果数量SELECT * FROM logs ORDER BY ts DESC LIMIT 10 OFFSET 20;OFFSET 效率低,大数据分页建议用游标或基于 ID
列别名SELECT expr AS alias重命名输出列SELECT name AS full_name FROM users;AS 可省略;别名可用于 ORDER BY
去重SELECT DISTINCT col FROM tbl;返回唯一值SELECT DISTINCT country FROM users;多列 DISTINCT 基于组合去重
聚合初探SELECT COUNT(*), MAX(age) FROM users;基础聚合SELECT COUNT(*) FROM orders;无 GROUP BY 时返回单行;NULL 值通常被忽略(COUNT(*) 除外)

第五章:高级 SQL 功能

5.1 聚合函数与 GROUP BY

方法/函数名称语法/说明用途代码示例注意事项
COUNTCOUNT(*)COUNT(column)统计行数;COUNT(*) 包含 NULL,COUNT(col) 忽略 NULLSELECT department, COUNT(*) FROM employees GROUP BY department;性能良好,常用于分组统计
SUMSUM(numeric_column)求和SELECT SUM(salary) FROM employees;仅适用于数值类型;全 NULL 返回 NULL
AVGAVG(numeric_column)求平均值SELECT AVG(age) FROM users;自动忽略 NULL 值;结果为 numeric 类型
MIN / MAXMIN(col), MAX(col)求最小/最大值SELECT MIN(created_at), MAX(created_at) FROM logs;适用于任意可排序类型(包括 TEXT、DATE)
GROUP BYSELECT col, agg(...) FROM tbl GROUP BY col;按列分组聚合SELECT status, COUNT(*) FROM orders GROUP BY status;SELECT 中非聚合列必须出现在 GROUP BY 中(除非使用 ANY_VALUE 等扩展)
HAVINGGROUP BY ... HAVING condition对分组结果过滤SELECT dept, AVG(sal) FROM emp GROUP BY dept HAVING AVG(sal) > 5000;不能用 WHERE 替代;WHERE 过滤行,HAVING 过滤组
STRING_AGGSTRING_AGG(text_col, delimiter)字符串拼接SELECT dept, STRING_AGG(name, ', ') FROM emp GROUP BY dept;可加 ORDER BY:STRING_AGG(name, ',' ORDER BY name)
ARRAY_AGGARRAY_AGG(col)聚合成数组SELECT user_id, ARRAY_AGG(tag) FROM user_tags GROUP BY user_id;保留 NULL 值;结果为数组类型

5.2 JOIN 操作(INNER, LEFT, RIGHT, FULL)

JOIN 类型语法/说明用途代码示例注意事项
INNER JOINFROM a INNER JOIN b ON a.id = b.a_id返回两表匹配的行SELECT u.name, o.total FROM users u INNER JOIN orders o ON u.id = o.user_id;等价于 JOIN(省略 INNER);不匹配行被丢弃
LEFT JOINFROM a LEFT JOIN b ON a.id = b.a_id返回左表所有行,右表无匹配则为 NULLSELECT u.name, o.id FROM users u LEFT JOIN orders o ON u.id = o.user_id;常用于”主表+可选附属信息”场景
RIGHT JOINFROM a RIGHT JOIN b ON a.id = b.a_id返回右表所有行,左表无匹配则为 NULLSELECT u.name, p.title FROM users u RIGHT JOIN posts p ON u.id = p.author_id;较少使用,多数可转为 LEFT JOIN
FULL OUTER JOINFROM a FULL JOIN b ON a.id = b.id返回两表所有行,无匹配侧为 NULLSELECT COALESCE(a.id, b.id), a.val, b.val FROM a FULL JOIN b ON a.id = b.id;需处理两侧 NULL;性能较低,慎用于大表
USING 子句FROM a JOIN b USING (common_col)简化等值连接(列名相同)SELECT * FROM orders JOIN customers USING (customer_id);结果中 common_col 仅出现一次
NATURAL JOINFROM a NATURAL JOIN b自动按同名列连接SELECT * FROM table1 NATURAL JOIN table2;极不推荐!易因新增同名列导致逻辑错误
CROSS JOINFROM a CROSS JOIN b笛卡尔积(无条件连接)SELECT * FROM colors CROSS JOIN sizes;结果行数 = 行数(a) × 行数(b),谨慎使用

5.3 子查询与 CTE(WITH 语句)

方法/结构名称语法/说明用途代码示例注意事项
标量子查询(SELECT col FROM tbl WHERE ...)返回单值,用于 SELECT/WHERESELECT name, (SELECT COUNT(*) FROM orders WHERE user_id = u.id) AS order_count FROM users u;必须返回 0 或 1 行 1 列;否则报错
行子查询(SELECT col1, col2 FROM tbl LIMIT 1)返回一行多列SELECT * FROM products WHERE (price, category) = (SELECT MAX(price), 'Electronics' FROM products);需用括号包裹;可用于比较元组
EXISTS 子查询WHERE EXISTS (SELECT 1 FROM tbl WHERE ...)判断是否存在匹配行SELECT * FROM users u WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);子查询通常用 SELECT 1,性能优于 COUNT
IN 子查询WHERE col IN (SELECT key FROM tbl)判断是否在结果集中SELECT * FROM products WHERE id IN (SELECT product_id FROM promotions);若子查询含 NULL,IN 可能返回 UNKNOWN(导致行被过滤)
CTE(公用表表达式)WITH cte_name AS (SELECT ...) SELECT ... FROM cte_name;定义临时结果集,提升可读性WITH active_users AS (SELECT id FROM users WHERE last_login > NOW() - INTERVAL '7 days') SELECT COUNT(*) FROM orders WHERE user_id IN (SELECT id FROM active_users);CTE 仅在当前语句有效;可递归(见下)
递归 CTEWITH RECURSIVE cte AS (base_case UNION ALL recursive_part) ...处理层次/图结构数据WITH RECURSIVE tree AS (SELECT id, parent_id FROM nodes WHERE parent_id IS NULL UNION ALL SELECT n.id, n.parent_id FROM nodes n JOIN tree t ON n.parent_id = t.id) SELECT * FROM tree;必须用 UNION ALL;需有终止条件,否则无限循环
多 CTEWITH a AS (...), b AS (...) SELECT ...定义多个临时结果集WITH sales AS (SELECT ...), targets AS (SELECT ...) SELECT s.region, s.amount / t.goal FROM sales s JOIN targets t ON s.region = t.region;各 CTE 间可用逗号分隔;后定义的可引用前面的

5.4 窗口函数(Window Functions)

函数/结构名称语法/说明用途代码示例注意事项
OVER() 子句func() OVER ([PARTITION BY cols] [ORDER BY cols] [frame_clause])定义窗口计算范围SELECT name, salary, AVG(salary) OVER (PARTITION BY dept) FROM employees;无 PARTITION BY 则整个结果集为一个窗口
ROW_NUMBER()ROW_NUMBER() OVER (ORDER BY col)为每行分配唯一序号SELECT *, ROW_NUMBER() OVER (ORDER BY score DESC) AS rank FROM students;即使值相同,序号也不同
RANK()RANK() OVER (ORDER BY col)跳跃排名(相同值同排名,后续跳过)SELECT name, score, RANK() OVER (ORDER BY score DESC) FROM students;如分数 100,100,90 → 排名 1,1,3
DENSE_RANK()DENSE_RANK() OVER (ORDER BY col)密集排名(相同值同排名,后续连续)SELECT ..., DENSE_RANK() OVER (ORDER BY score DESC) FROM students;如 100,100,90 → 排名 1,1,2
LAG / LEADLAG(col, offset, default) OVER (ORDER BY time)访问前/后行数据SELECT ts, value, LAG(value) OVER (ORDER BY ts) AS prev_value FROM sensor_data;offset 默认为 1;default 默认为 NULL
FIRST_VALUE / LAST_VALUEFIRST_VALUE(col) OVER (ORDER BY ... ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)获取窗口首/末值SELECT id, group_id, FIRST_VALUE(id) OVER (PARTITION BY group_id ORDER BY id) FROM items;LAST_VALUE 默认窗口可能不包含全部行,需显式指定 frame
窗口帧(Frame Clause)ROWS BETWEEN start AND endRANGE BETWEEN ...精确控制窗口行范围SUM(sales) OVER (ORDER BY month ROWS 2 PRECEDING)常用:UNBOUNDED PRECEDING、CURRENT ROW、N PRECEDING/FOLLOWING
累积和SUM(col) OVER (ORDER BY time ROWS UNBOUNDED PRECEDING)计算累计值SELECT date, revenue, SUM(revenue) OVER (ORDER BY date) AS running_total FROM daily_sales;必须指定 ORDER BY,否则 SUM 作用于整个分区

第六章:索引与性能优化

6.1 索引类型(B-tree, Hash, GIN, GiST)

索引类型语法/说明用途代码示例注意事项
B-tree默认索引类型;支持等值、范围、排序查询通用场景(如主键、外键、WHERE col = ? 或 col > ?)CREATE INDEX idx_users_email ON users(email);支持 ASC/DESC、NULLS FIRST/LAST;适用于大多数数据类型
Hash仅支持等值查询(=)高速精确匹配(不支持排序或范围)CREATE INDEX idx_status_hash ON orders USING HASH(status);仅在 PostgreSQL ≥10 中可用于 WAL 日志(可复制);不支持多列
GIN(Generalized Inverted Index)倒排索引;适用于数组、JSONB、全文搜索查询包含特定元素的复合结构CREATE INDEX idx_tags_gin ON articles USING GIN(tags);CREATE INDEX idx_meta_gin ON products USING GIN(metadata JSONB_PATH_OPS);插入/更新开销大;适合读多写少场景
GiST(Generalized Search Tree)支持多种”相似性”操作(如几何、全文搜索、范围类型)全文检索、地理空间(PostGIS)、范围重叠查询CREATE INDEX idx_docs_gist ON documents USING GiST(content_tsvector);CREATE INDEX idx_events_gist ON events USING GiST(period tsrange);可能返回假阳性(需 recheck);比 GIN 更节省空间
BRIN(Block Range Index)按数据块记录 min/max 值超大表且数据物理有序(如时间序列日志)CREATE INDEX idx_logs_brin ON logs USING BRIN(created_at);极小存储开销;仅当数据按索引列物理排序时高效
SP-GiST空间分区 GiST;支持非平衡树结构IP 路由、电话号码前缀、k-d 树等CREATE INDEX idx_ips_spgist ON network USING SPGiST(ip inet);使用场景较 niche;需明确匹配操作符类

6.2 创建与管理索引

方法/命令名称语法/说明用途代码示例注意事项
CREATE INDEXCREATE [UNIQUE] INDEX name ON table (col [ASC|DESC] [NULLS FIRST/LAST]);创建普通索引CREATE INDEX idx_orders_user_id ON orders(user_id);默认并发构建会锁表(禁止写);大表建议用 CONCURRENTLY
CREATE INDEX CONCURRENTLYCREATE INDEX CONCURRENTLY name ON table (col);不阻塞写操作地创建索引CREATE INDEX CONCURRENTLY idx_users_name ON users(name);执行时间更长;若失败会留下 INVALID 索引,需手动 DROP
多列索引CREATE INDEX ON tbl (col1, col2);支持组合条件查询CREATE INDEX idx_orders_status_date ON orders(status, created_at);最左前缀原则:WHERE status = ? AND created_at > ? 可用;仅 created_at 不能用
部分索引(Partial Index)CREATE INDEX ... WHERE condition;仅索引满足条件的行CREATE INDEX idx_active_users ON users(id) WHERE active = true;节省空间和维护开销;查询需包含相同 WHERE 条件才能命中
表达式索引CREATE INDEX ON tbl ((lower(email)));对函数/表达式结果建索引CREATE INDEX idx_users_email_lower ON users((lower(email)));查询必须使用相同表达式:WHERE lower(email) = 'a@example.com'
DROP INDEXDROP INDEX [IF EXISTS] name;删除索引DROP INDEX IF EXISTS idx_old;删除后查询可能变慢;无回滚机制
重建索引REINDEX INDEX name;REINDEX TABLE tbl;修复膨胀或损坏的索引REINDEX INDEX idx_users_email;会锁表(禁止读写);PG ≥12 可用 REINDEX CONCURRENTLY(实验性)
查看索引\d table_name 或查询 pg_indexes列出表的索引SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'users';\d+ table 显示更详细信息(包括索引大小)

6.3 EXPLAIN 与查询计划分析

方法/命令名称语法/说明用途代码示例注意事项
EXPLAINEXPLAIN SELECT ...;显示查询执行计划(估算)EXPLAIN SELECT * FROM users WHERE email = 'a@example.com';默认输出为”计划树”,显示节点类型、成本估算
EXPLAIN ANALYZEEXPLAIN (ANALYZE, BUFFERS) SELECT ...;实际执行并返回运行时统计EXPLAIN (ANALYZE, BUFFERS) SELECT COUNT(*) FROM logs;会真实执行查询!生产环境慎用;显示实际时间、行数、I/O 等
输出字段含义cost=startup..total, rows=估算行数, width=平均行宽理解计划成本模型Seq Scan on users (cost=0.00..12.50 rows=1 width=64)cost 单位为磁盘页读取;rows 是优化器估算,可能不准
常见节点类型Seq Scan(全表扫描)、Index Scan、Bitmap Heap Scan、Hash Join、Nested Loop识别执行策略Index Scan using idx_users_email on usersIndex Scan 适合少量行;Bitmap Scan 适合中等数量
缓冲区信息BUFFERS 选项显示 shared/local/temp read/hit分析 I/O 性能Buffers: shared hit=10 read=5hit 表示缓存命中;read 表示从磁盘读取
触发器与函数EXPLAIN 不显示触发器执行;函数内 SQL 需单独分析注意黑盒操作复杂函数可能隐藏性能瓶颈
强制禁用索引SET enable_indexscan = off;测试不同计划(调试用)SET enable_seqscan = off; EXPLAIN SELECT ...;仅当前会话有效;切勿用于生产

6.4 VACUUM 与 ANALYZE

方法/命令名称语法/说明用途代码示例注意事项
VACUUMVACUUM [table];回收死元组空间(MVCC 产生)VACUUM users;不释放空间给 OS(仅标记为可复用);可并发执行
VACUUM FULLVACUUM FULL [table];重建表并释放空间给 OSVACUUM FULL logs;锁表(禁止读写);耗时长;仅在空间极度紧张时使用
ANALYZEANALYZE [table [(column [, ...])]];收集表统计信息供优化器使用ANALYZE orders;自动由 autovacuum 触发;也可手动运行以更新统计
VACUUM ANALYZEVACUUM ANALYZE table;同时回收空间并更新统计VACUUM ANALYZE sessions;常用于大批量 UPDATE/DELETE 后
autovacuum后台进程自动执行 VACUUM/ANALYZE防止表膨胀和统计过期无需手动调用通过 postgresql.conf 配置:autovacuum_vacuum_scale_factor
查看膨胀情况查询 pg_stat_user_tablesn_dead_tup判断是否需手动 VACUUMSELECT schemaname, tablename, n_dead_tup FROM pg_stat_user_tables WHERE n_dead_tup > 1000;死元组过多会导致查询变慢、WAL 增长
FREEZEVACUUM FREEZE table;防止事务 ID 回卷(wraparound)VACUUM FREEZE large_table;通常由 autovacuum 自动处理;极端情况下需手动干预
成本延迟控制vacuum_cost_delay, vacuum_cost_limit控制 VACUUM I/O 资源占用postgresql.conf 中调整避免 VACUUM 影响在线业务性能

第七章:事务与并发控制

7.1 事务基础(BEGIN, COMMIT, ROLLBACK)

方法/命令名称语法/说明用途代码示例注意事项
BEGIN / START TRANSACTIONBEGIN;START TRANSACTION;显式开启一个事务块BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1;PostgreSQL 中每个语句默认自动提交;显式 BEGIN 禁用自动提交
COMMITCOMMIT;提交当前事务,使更改持久化COMMIT;提交后无法回滚;WAL 日志确保持久性
ROLLBACKROLLBACK;回滚当前事务,丢弃所有更改ROLLBACK;可在任何时刻执行;包括因错误自动回滚
SAVEPOINTSAVEPOINT name;在事务内设置保存点BEGIN; INSERT INTO logs VALUES (1); SAVEPOINT sp1; DELETE FROM temp; ROLLBACK TO sp1; COMMIT;允许部分回滚;可嵌套多个保存点
ROLLBACK TO SAVEPOINTROLLBACK TO SAVEPOINT name;回滚到指定保存点ROLLBACK TO sp1;保存点之后的操作被撤销,但事务仍继续
隐式事务单条 SQL 语句自动作为事务执行简化简单操作UPDATE users SET name = 'Alice' WHERE id = 1;即使未显式 BEGIN,也满足 ACID;失败则整条语句回滚
事务结束行为执行 COMMIT/ROLLBACK 后自动退出事务模式返回自动提交状态下一条语句又成为独立事务

7.2 隔离级别(READ COMMITTED, SERIALIZABLE 等)

隔离级别语法/说明用途代码示例注意事项
READ COMMITTED默认隔离级别;只能看到已提交数据平衡一致性与并发性BEGIN ISOLATION LEVEL READ COMMITTED;同一事务内多次 SELECT 可能返回不同结果(不可重复读)
REPEATABLE READ事务内首次读取建立快照,后续读一致防止不可重复读BEGIN ISOLATION LEVEL REPEATABLE READ;PostgreSQL 中实际提供快照隔离(SI),强于标准 RR
SERIALIZABLE最高隔离;防止幻读、写偏斜等严格串行化执行效果BEGIN ISOLATION LEVEL SERIALIZABLE;若检测到冲突(如写偏斜),会报错 serialization_failure,需重试
设置方式SET TRANSACTION ISOLATION LEVEL level;(在 BEGIN 后首条语句)动态指定当前事务隔离级别BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;也可在连接时通过 default_transaction_isolation GUC 设置默认值
幻读处理SERIALIZABLE 级别下,新增行导致的幻读会被检测并拒绝提交保证逻辑一致性READ COMMITTED 和 REPEATABLE READ 不阻止幻读(但 PG 的 RR 实际避免了多数幻读)
写偏斜(Write Skew)两个事务读取相同数据集,各自修改互斥部分,导致不一致SERIALIZABLE 可检测此类冲突例如:两人同时检查库存充足后各减 1,总和超限仅 SERIALIZABLE 能可靠防止;需应用层重试机制

7.3 锁机制与死锁处理

锁类型/操作名称语法/说明用途代码示例注意事项
行级锁(FOR UPDATE)SELECT ... FOR UPDATE;获取行排他锁,防止其他事务修改SELECT * FROM accounts WHERE id = 1 FOR UPDATE;锁持续到事务结束;阻塞其他 FOR UPDATE/FOR NO KEY UPDATE
行级锁(FOR SHARE)SELECT ... FOR SHARE;获取行共享锁,允许读但阻塞写SELECT * FROM products WHERE id = 100 FOR SHARE;其他事务可 FOR SHARE,但不能 FOR UPDATE
FOR NO KEY UPDATESELECT ... FOR NO KEY UPDATE;弱于 FOR UPDATE,不阻塞 KEY SHARESELECT * FROM orders WHERE id = 123 FOR NO KEY UPDATE;适用于不修改主键/唯一键的更新
FOR KEY SHARESELECT ... FOR KEY SHARE;弱共享锁,仅阻塞修改主键/唯一键SELECT * FROM users WHERE id = 1 FOR KEY SHARE;允许并发 UPDATE 非键列
表级锁(LOCK TABLE)LOCK TABLE tbl IN MODE MODE;显式获取表锁LOCK TABLE orders IN EXCLUSIVE MODE;ACCESS EXCLUSIVE(如 ALTER TABLE)会阻塞所有其他操作;MODE: ACCESS SHARE, ROW EXCLUSIVE, SHARE, EXCLUSIVE, ACCESS EXCLUSIVE
查看锁信息查询 pg_lockspg_stat_activity诊断阻塞或死锁SELECT blocked_locks.pid AS blocked_pid, blocking_locks.pid AS blocking_pid FROM pg_catalog.pg_locks blocked_locks JOIN pg_catalog.pg_locks blocking_locks ON ...被阻塞会话的 wait_event_type = 'Lock'
死锁检测自动检测循环等待并终止一个事务避免永久阻塞报错:deadlock detected;应用需捕获并重试
避免死锁策略按固定顺序访问表/行减少死锁概率总是先更新 accounts 表再更新 logs 表无法完全避免,但可大幅降低发生率

7.4 MVCC(多版本并发控制)原理

概念名称说明用途注意事项
元组可见性每行(元组)包含 xmin(创建事务 ID)、xmax(删除/更新事务 ID)判断当前事务是否能看到该行事务只能看到:xmin ≤ 当前事务 ID 且 xmax = 0 或 xmax ≥ 当前事务 ID(且未提交)
快照(Snapshot)事务开始时记录活跃事务 ID 集合确定哪些修改对本事务不可见快照在 READ COMMITTED 下每条语句刷新,REPEATABLE READ/SERIALIZABLE 下整个事务固定
版本链更新/删除不立即覆盖原行,而是保留旧版本并标记 xmax支持历史版本读取旧版本由 VACUUM 清理;未清理前占用空间(“膨胀”)
无读写阻塞读操作不加锁,写操作不阻塞读高并发读写性能写操作之间仍可能冲突(如更新同一行)
事务 ID 回卷(Wraparound)32 位事务 ID 循环使用(约 42 亿)防止 ID 耗尽需定期 FREEZE(将 xmin 设为 FrozenTransactionId);autovacuum 自动处理
CLOG(Commit Log)记录每个事务的提交状态(in-progress / committed / aborted)判断 xmax 对应事务是否已提交存储在 pg_xact 目录;影响可见性判断
HOT(Heap-Only Tuples)若更新未改变索引列,则新版本与旧版本在同一页面减少索引更新开销提升 UPDATE 性能;需 fillfactor < 100 预留空间

第八章:备份与恢复

8.1 逻辑备份(pg_dump / pg_restore)

方法/命令名称语法/说明用途代码示例注意事项
pg_dump(纯 SQL 格式)pg_dump -U user -d dbname > backup.sql导出数据库为可读 SQL 脚本pg_dump -U postgres myapp > myapp_20260202.sql默认包含 CREATE TABLE、INSERT 等;不含角色和表空间
pg_dump(自定义格式)pg_dump -Fc -f backup.dump dbname生成压缩、可选择性恢复的二进制格式pg_dump -Fc -f myapp.dump myapp必须用 pg_restore 恢复;支持并行、按表恢复
pg_dumpallpg_dumpall > cluster.sql备份整个集群(含角色、表空间、所有数据库)pg_dumpall -U postgres > full_cluster.sql包含全局对象;恢复时需先创建角色
pg_restorepg_restore -U user -d dbname backup.dump从自定义/目录格式恢复pg_restore -U postgres -d myapp myapp.dump可加 -j 4 并行恢复(仅自定义/目录格式支持)
仅结构备份pg_dump -s -d dbname仅导出 DDL(无数据)pg_dump -s myapp > schema.sql用于迁移表结构
仅数据备份pg_dump -a -d dbname仅导出 INSERT 语句(无 DDL)pg_dump -a myapp > data.sql需目标库已有相同结构
指定模式/表pg_dump -n schema_name-t table_name按需备份部分对象pg_dump -t users -t orders myapp > partial.sql支持通配符:-t 'user*'
一致性保证pg_dump 默认在单事务中运行(--serializable-deferrable 可选)确保备份数据一致pg_dump --serializable-deferrable -d myapp大库备份期间仍允许读写

8.2 物理备份(文件系统级 + WAL)

方法/操作名称语法/说明用途代码示例注意事项
基础物理备份停库后直接复制整个数据目录($PGDATA快速完整备份systemctl stop postgresql && cp -r /var/lib/postgresql/16/main /backup/pg_base必须停库(或使用 pg_basebackup);恢复时需替换整个数据目录
pg_basebackuppg_basebackup -D /backup/dir -Fp -Xs -P -R在线物理备份(无需停库)pg_basebackup -h localhost -U replicator -D /backup/base -Fp -Xs -P -R需配置 replication 权限;-R 自动生成 recovery.signal 和 primary_conninfo
备份格式-Fp(plain,目录)或 -Ft(tar)控制输出格式pg_basebackup -Ft -z -D /backup/tar-Fp 更易管理;-Ft 适合网络传输
WAL 包含选项-Xs(stream,实时流 WAL)、-Xf(fetch,备份后获取)确保备份可恢复到一致状态-Xs 推荐,避免备份期间 WAL 被清理
恢复物理备份替换 $PGDATA 目录,启动 PostgreSQL从物理备份还原实例rm -rf /var/lib/postgresql/16/main && cp -r /backup/base /var/lib/postgresql/16/main && systemctl start postgresql需确保权限正确(通常属主为 postgres);版本必须完全兼容
表空间处理pg_basebackup 自动处理符号链接备份含表空间的实例表空间路径需在目标机存在或重定向
备份验证启动备份副本并连接测试确认备份可用pg_ctl -D /backup/base start && psql -h /tmp -d postgres -c "SELECT version();"定期验证是良好实践

8.3 持续归档与时间点恢复(PITR)

概念/操作名称语法/说明用途代码示例注意事项
WAL 归档配置postgresql.conf 中设置:archive_mode = onarchive_command = 'cp %p /wal_archive/%f'将 WAL 文件持续复制到归档位置archive_command = 'test ! -f /archive/%f && cp %p /archive/%f'%p=WAL 路径,%f=文件名;命令返回 0 表示成功
基准备份 + WAL先做 pg_basebackup,再持续归档 WAL实现任意时间点恢复基准备份是 PITR 起点;WAL 必须连续
恢复目标配置创建 recovery.signal,并在 postgresql.confpostgresql.auto.conf 中设置:restore_command = 'cp /wal_archive/%f %p'recovery_target_time = '2026-02-01 12:00:00'指定恢复到的时间/事务/LSNrecovery_target_name = 'before_deploy'(配合 pg_create_restore_point恢复完成后自动删除 recovery.signal
创建还原点SELECT pg_create_restore_point('name');标记可恢复的命名点SELECT pg_create_restore_point('pre_upgrade');便于精确回滚到关键操作前
时间线(Timeline)每次 PITR 后生成新 timeline防止 WAL 覆盖历史分支恢复后 WAL 文件名含 timeline ID(如 00000002.history多次 PITR 需管理多 timeline WAL
恢复后提升pg_ctl promote 或创建 promote.signal将恢复中的实例转为主库touch $PGDATA/promote.signal结束只读恢复模式,开始接受写入
归档失败处理archive_command 失败,WAL 不会被清理防止数据丢失需监控归档命令日志;磁盘满会导致数据库暂停

8.4 备份策略与自动化脚本

策略/操作名称说明用途代码示例(简化)注意事项
全量 + 增量组合每周一次 pg_basebackup(全量),每日 pg_dump(逻辑增量)平衡恢复速度与存储成本0 2 * * 0 /backup/full.sh0 2 * * 1-6 /backup/daily.sh逻辑备份适合小表;物理备份适合大库
WAL 归档保留保留至少 7 天 WAL + 最近 2 个基准备份支持 PITR 回溯窗口find /wal_archive -mtime +7 -delete需计算 WAL 生成速率,避免空间耗尽
自动化脚本要素1. 错误检查;2. 日志记录;3. 备份验证;4. 清理旧备份提高可靠性if ! pg_dump mydb > /b/mydb.sql; then echo "Fail" >> /var/log/backup.log; exit 1; fi使用 set -e 确保脚本遇错退出
加密与传输使用 gpg 加密、rsync/scp 传输到异地满足安全与容灾要求pg_dump mydb | gzip | gpg -c --passphrase-file key > mydb.sql.gz.gpg密钥需安全保管;考虑使用 Vault 或 KMS
监控与告警检查备份文件大小、时间、日志错误及早发现备份失败if [ $(stat -c%s /b/latest.dump) -lt 1000 ]; then alert "Backup too small"; fi集成到 Prometheus/Zabbix 等监控系统
测试恢复流程每季度执行完整恢复演练验证备份有效性在隔离环境:pg_ctl -D /test_restore start && psql -d testdb -c "SELECT COUNT(*) FROM critical_table;"”未测试的备份等于没有备份”
使用 pgBackRest / Barman第三方工具提供企业级备份管理简化 PITR、压缩、加密、远程存储pgbackrest --stanza=mydb backup推荐用于生产环境;比原生工具更健壮

第九章:扩展与高级功能

9.1 扩展安装与管理(CREATE EXTENSION)

方法/命令名称语法/说明用途代码示例注意事项
CREATE EXTENSIONCREATE EXTENSION [IF NOT EXISTS] extension_name [WITH SCHEMA schema_name];在当前数据库中启用扩展CREATE EXTENSION IF NOT EXISTS "uuid-ossp";扩展必须已安装到 PostgreSQL 的 share/extension/ 目录
DROP EXTENSIONDROP EXTENSION [IF EXISTS] extension_name [CASCADE];卸载扩展及其对象DROP EXTENSION "hstore";CASCADE 会删除依赖该扩展的对象(如使用 hstore 的表)
查看已安装扩展\dx 或查询 pg_extension列出当前数据库启用的扩展SELECT extname, extversion FROM pg_extension;不同数据库可启用不同扩展
常用官方扩展uuid-ossp(UUID 生成)、pgcrypto(加密)、hstore(键值存储)、postgis(地理空间)提供额外数据类型与函数CREATE EXTENSION postgis;部分扩展需操作系统包(如 postgresql-contrib)
扩展脚本位置$PGSHARE/extension/extension_name--version.sql定义扩展安装逻辑升级通过 ALTER EXTENSION UPDATE TO 'new_version';
扩展权限通常仅超级用户可 CREATE/DROP控制扩展安装安全可通过 GRANT CREATE ON DATABASE db TO user; 允许非超级用户安装(PG ≥15)
扩展依赖某些扩展依赖其他扩展或库确保环境完整CREATE EXTENSION postgis; 需 libgeos 等安装前需确认系统依赖已满足

9.2 JSON / JSONB 数据类型与操作

方法/操作名称语法/说明用途代码示例注意事项
JSON vs JSONBJSON:文本存储,保留空格和键顺序;JSONB:二进制存储,去重键、忽略空格JSONB 支持索引和高效查询;JSON 适合日志等原始存储metadata JSONB推荐优先使用 JSONB
插入 JSONB直接写 JSON 字面量或使用函数存储半结构化数据INSERT INTO logs (data) VALUES ('{"user": "alice", "action": "login"}'::JSONB);自动验证 JSON 格式
-> 操作符col->'key' 返回 JSONB 对象的字段(结果为 JSONB)提取嵌套值SELECT data->'user' FROM logs;若 key 不存在,返回 NULL
->> 操作符col->>'key' 返回文本形式的字段值用于 WHERE 或显示SELECT data->>'user' AS username FROM logs;结果为 TEXT 类型
#> 操作符col#>'{a,b,c}' 按路径提取嵌套值多层嵌套访问SELECT config#>'{database,host}' FROM apps;路径为文本数组
? 操作符'key' ? col 判断 JSONB 是否包含指定键条件过滤SELECT * FROM logs WHERE data ? 'error';仅适用于 JSONB
@> 操作符col @> '{"k":"v"}' 判断是否包含子集包含查询SELECT * FROM products WHERE specs @> '{"color": "red"}';可配合 GIN 索引加速
jsonb_setjsonb_set(target, path, new_value [, create_missing])修改 JSONB 中的值UPDATE logs SET data = jsonb_set(data, '{status}', '"processed"');create_missing 默认 true
索引支持GIN 索引加速包含、键存在等查询提升 JSONB 查询性能CREATE INDEX idx_logs_data ON logs USING GIN (data); 或更高效:CREATE INDEX idx_logs_data_ops ON logs USING GIN (data jsonb_path_ops);jsonb_path_ops 仅支持 @>,但更小更快
转换函数to_jsonb(row)jsonb_build_object()构造 JSONBSELECT jsonb_build_object('id', id, 'name', name) FROM users;row_to_json() 用于 JSON 类型

9.3 全文搜索(tsvector / tsquery)

方法/操作名称语法/说明用途代码示例注意事项
tsvector文本的词位向量(经分词、去停用词、词干化)存储可搜索的文档表示body_ts tsvector通常由触发器自动维护
tsquery搜索条件(词位 + 布尔操作符)表达查询意图'search & engine'支持 &(AND)、|(OR)、!(NOT)
to_tsvectorto_tsvector([config,] document)将文本转为 tsvectorSELECT to_tsvector('english', 'The quick brown fox');'brown':3 'fox':4 'quick':2config 控制分词规则(如 english、simple)
to_tsqueryto_tsquery([config,] querytext)将查询字符串转为 tsquerySELECT to_tsquery('english', 'quick & fox');自动词干化;不支持短语搜索
plainto_tsqueryplainto_tsquery([config,] phrase)将自然语言转为 AND 查询SELECT plainto_tsquery('english', 'quick brown fox');'quick' & 'brown' & 'fox'更适合用户输入
@@ 操作符tsvector @@ tsquery执行全文匹配SELECT * FROM articles WHERE body_ts @@ to_tsquery('english', 'database');返回 boolean
全文索引GIN 或 GiST 索引加速 @@ 查询提升搜索性能CREATE INDEX idx_articles_ts ON articles USING GIN (body_ts);GIN 更快但更大;GiST 更小但慢
高亮结果ts_headline([config,] document, query [, options])显示匹配片段并高亮SELECT ts_headline('english', body, q) FROM articles, to_tsquery('english', 'search') q WHERE body_ts @@ q;默认用 <b>...</b> 高亮
权重与排序setweight(tsvector, 'A'/'B'/'C'/'D') + ts_rank()按字段重要性排序UPDATE articles SET title_ts = setweight(to_tsvector(title), 'A'), body_ts = setweight(to_tsvector(body), 'B');SELECT *, ts_rank(title_ts || body_ts, q) FROM ...权重 A 最高,D 最低
自定义配置创建文本搜索配置(CREATE TEXT SEARCH CONFIGURATION支持中文、专业术语等需集成外部分词器(如 zhparser)官方不直接支持中文,需第三方扩展

9.4 分区表与继承表

方法/操作名称语法/说明用途代码示例注意事项
声明式分区(PG ≥10)CREATE TABLE parent (...) PARTITION BY RANGE (col);CREATE TABLE child PARTITION OF parent FOR VALUES FROM (min) TO (max);按范围、列表或哈希自动路由数据CREATE TABLE logs (ts TIMESTAMPTZ, msg TEXT) PARTITION BY RANGE (ts);CREATE TABLE logs_202601 PARTITION OF logs FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');推荐方式;优化器可分区裁剪(partition pruning)
列表分区PARTITION BY LIST (status)按离散值分区CREATE TABLE orders PARTITION BY LIST (country);CREATE TABLE orders_us PARTITION OF orders FOR VALUES IN ('US');适合状态、区域等枚举字段
哈希分区PARTITION BY HASH (id)均匀分布数据CREATE TABLE users PARTITION BY HASH (id);CREATE TABLE users_p0 PARTITION OF users FOR VALUES WITH (MODULUS 4, REMAINDER 0);适合无自然分界的大表
继承表(旧方式)CREATE TABLE child () INHERITS (parent);手动实现分区(PG <10)CREATE TABLE logs_202601 (CHECK (ts >= '2026-01-01' AND ts < '2026-02-01')) INHERITS (logs);需手动创建触发器路由 INSERT;无分区裁剪优化
分区维护添加/删除分区表管理时间序列数据生命周期DROP TABLE logs_202501;CREATE TABLE logs_202603 PARTITION OF logs FOR VALUES FROM ('2026-03-01') TO ('2026-04-01');删除分区即删除数据;添加新分区无需锁主表
分区索引在父表建索引,自动应用到所有分区统一索引管理CREATE INDEX ON logs (ts);PG ≥11 支持;各分区有独立索引
查询父表SELECT * FROM parent WHERE ...自动扫描相关分区SELECT COUNT(*) FROM logs WHERE ts > '2026-01-15';优化器跳过无关分区(需条件含分区键)
分区限制不支持主键跨分区、BEFORE ROW 触发器等注意功能边界主键必须包含分区键;外键需谨慎设计

第十章:命令行运维与监控

10.1 查看连接与活动会话(pg_stat_activity)

方法/查询名称语法/说明用途代码示例注意事项
查询 pg_stat_activitySELECT * FROM pg_stat_activity;查看所有当前会话状态SELECT pid, usename, application_name, state, query FROM pg_stat_activity;需要适当权限(通常超级用户或 pg_read_all_stats 角色)
活动会话过滤WHERE state = 'active'仅显示正在执行的查询SELECT pid, query, now() - query_start AS duration FROM pg_stat_activity WHERE state = 'active';state 可为 active、idle、idle in transaction 等
长事务检测WHERE now() - xact_start > interval '5 minutes'发现长时间未提交事务SELECT pid, usename, xact_start, query FROM pg_stat_activity WHERE xact_start IS NOT NULL AND now() - xact_start > '10 min';长事务阻塞 VACUUM,导致膨胀
终止会话SELECT pg_terminate_backend(pid);强制断开指定会话SELECT pg_terminate_backend(12345);会回滚该会话未提交事务;比 pg_cancel_backend 更彻底
取消查询SELECT pg_cancel_backend(pid);仅取消当前正在执行的查询SELECT pg_cancel_backend(12345);会话保持连接,可继续执行新语句
应用名识别application_name 字段识别客户端来源SELECT application_name, COUNT(*) FROM pg_stat_activity GROUP BY application_name;应用应设置有意义的 application_name(如 “web-api”)
等待事件分析wait_event_type, wait_event诊断性能瓶颈SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event IS NOT NULL;常见:Lock(锁等待)、IO(磁盘 I/O)、Client(等待客户端)

10.2 日志配置与查看

配置项/操作名称语法/说明用途代码示例(postgresql.conf)注意事项
logging_collectorlogging_collector = on启用日志写入文件(而非 stderr)logging_collector = on必须开启才能使用 log_directory 等选项
log_directory / log_filenamelog_directory = 'log'log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'控制日志存储位置与命名log_directory = '/var/log/postgresql'路径相对于 $PGDATA,除非是绝对路径
log_statementlog_statement = 'all' | 'ddl' | 'mod' | 'none'记录 SQL 语句log_statement = 'mod''mod' 记录 INSERT/UPDATE/DELETE;'all' 影响性能,慎用于生产
log_min_duration_statementlog_min_duration_statement = 1000记录超过阈值(毫秒)的慢查询log_min_duration_statement = 500设为 0 相当于 log_statement='all';常用于性能分析
log_connections / log_disconnectionslog_connections = onlog_disconnections = on记录客户端连接/断开事件log_connections = on有助于审计和排查连接泄漏
log_checkpointslog_checkpoints = on记录检查点详细信息log_checkpoints = on用于分析 I/O 峰值和恢复时间
查看日志文件使用系统命令查看实时监控日志tail -f /var/lib/postgresql/16/main/log/postgresql-*.log日志轮转由 log_rotation_age / log_rotation_size 控制
CSV 日志格式log_destination = 'csvlog'生成结构化日志便于分析log_destination = 'stderr,csvlog'CSV 文件含固定字段,适合导入 ELK 等系统

10.3 使用 pg_ctl 管理服务

命令/操作名称语法/说明用途代码示例注意事项
pg_ctl startpg_ctl -D datadir start启动 PostgreSQL 实例pg_ctl -D /var/lib/postgresql/16/main start需由 postgres 用户执行;默认前台启动,加 -l logfile 可后台
pg_ctl stoppg_ctl -D datadir stop [-m mode]停止实例pg_ctl -D /data stop -m fast-m 模式:smart(默认,等连接结束)、fast(回滚活跃事务)、immediate(立即终止,下次启动需恢复)
pg_ctl restartpg_ctl -D datadir restart重启服务pg_ctl -D /data restart等价于 stop + start
pg_ctl reloadpg_ctl -D datadir reload重载配置(不中断服务)pg_ctl -D /data reload仅对支持 SIGHUP 的参数生效(如 shared_buffers 无效)
pg_ctl statuspg_ctl -D datadir status检查服务是否运行pg_ctl -D /data status返回进程 PID 或提示未运行
pg_ctl promotepg_ctl -D datadir promote将备库提升为主库pg_ctl -D /standby_data promote用于流复制故障转移
指定用户/端口通过环境变量或配置多实例管理export PGDATA=/data2 && pg_ctl start或使用 -o "-p 5433" 指定额外启动参数
日志输出控制-l logfile 指定日志文件避免日志混杂pg_ctl -D /data -l /var/log/pg.log start若未指定,日志输出到终端或 systemd journal

10.4 常用监控命令与脚本

监控项/命令名称语法/说明用途代码示例注意事项
查看数据库大小SELECT pg_size_pretty(pg_database_size('dbname'));评估存储占用SELECT datname, pg_size_pretty(pg_database_size(datname)) FROM pg_database;pg_size_pretty() 将字节转为易读单位(MB/GB)
查看表大小pg_relation_size('table') + pg_total_relation_size()分析大表SELECT tablename, pg_size_pretty(pg_total_relation_size(tablename::regclass)) FROM pg_tables WHERE schemaname = 'public';pg_total_relation_size 包含索引和 TOAST
锁等待监控脚本查询阻塞链诊断锁竞争SELECT blocked.pid AS blocked_pid, blocked.query AS blocked_query, blocking.pid AS blocking_pid, blocking.query AS blocking_query FROM pg_catalog.pg_locks blocked_locks JOIN pg_catalog.pg_stat_activity blocked ON blocked.pid = blocked_locks.pid JOIN pg_catalog.pg_locks blocking_locks ON (blocking_locks.transactionid = blocked_locks.transactionid AND blocking_locks.pid != blocked_locks.pid) JOIN pg_catalog.pg_stat_activity blocking ON blocking.pid = blocking_locks.pid WHERE NOT blocked_locks.granted;定期运行可发现长期阻塞
自动清理状态SELECT * FROM pg_stat_progress_vacuum;监控 VACUUM 进度SELECT pid, datname, relname, phase, heap_blks_scanned, heap_blks_total FROM pg_stat_progress_vacuum;PG ≥13 支持
WAL 发送状态(主库)SELECT * FROM pg_stat_replication;监控流复制延迟SELECT application_name, client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn FROM pg_stat_replication;LSN 差值反映备库延迟
检查点统计SELECT * FROM pg_stat_bgwriter;分析 I/O 压力SELECT checkpoints_timed, checkpoints_req, buffers_checkpoint FROM pg_stat_bgwriter;checkpoints_req 高表示 shared_buffers 不足
简单健康检查脚本psql -c "SELECT 1;"验证服务可用性if psql -d postgres -c "SELECT 1;" >/dev/null 2>&1; then echo "OK"; else echo "DOWN"; fi可集成到 Nagios/Zabbix
磁盘空间预警df -h $PGDATA防止磁盘写满[ $(df -P /var/lib/postgresql | awk 'NR==2 {print $5}' | tr -d '%') -gt 80 ] && echo "WARNING: Disk usage > 80%"建议磁盘使用率不超过 80%