PG实战笔记 | 09 PostgreSQL psql客户端基本操作
上一篇我们完成了性能参数调优。这一篇,我们聊一个被很多人低估的工具:psql。它看起来只是一个黑底白字的命令行,但真正用熟之后,你会发现它比大多数图形化工具都高效——元命令、变量、脚本、监控,样样都能做。这一篇,我们把 psql 从“连接工具”升级为“运维利器”。
一、连接方式:不止 psql -U postgres
psql 支持多种连接方式,日常开发中最常用的是命令行参数:
psql-hlocalhost-p5432-Upostgres-dmydb-h:主机地址-p:端口,默认 5432-U:用户名-d:数据库名
但在复杂环境中,参数多了容易记错。更推荐使用连接字符串:
# URI 格式psql"postgresql://postgres:password@localhost:5432/mydb?sslmode=require"# conninfo 格式psql"host=localhost port=5432 dbname=mydb user=postgres"URI 格式的通用结构是postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]。连接字符串支持附带sslmode等参数,适合远程连接和生产环境。
密码管理的最佳实践:不要在命令行中直接写密码(会出现在ps aux中),也不要依赖PGPASSWORD环境变量。使用~/.pgpass文件——psql 会自动读取,权限设为600,安全且无感。
二、信息查询:\d 系列是日常使用频率最高的命令
psql 的元命令以反斜杠\开头,其中最核心的是\d系列。掌握这些命令,你可以在不写任何 SQL 的情况下摸清数据库全貌。
列出所有数据库
\l-- 列出所有数据库\l+-- 附带大小、表空间、描述\l是连接后第一个该执行的命令,确认自己连到了正确的数据库。
切换数据库
\c mydb-- 切换到 mydb\c mydb postgres-- 以 postgres 用户切换到 mydb查看表结构
\d users-- 查看 users 表的列、索引、约束\d+users-- 附带注释和磁盘大小\d不仅显示列名和类型,还会显示索引、主键、外键、触发器、访问权限——基本上是这个表的完整画像。
按对象类型列出
\d系列有一套完整的变体,按对象类型过滤:
| 命令 | 作用 |
|---|---|
\dt | 仅表 |
\di | 仅索引 |
\dv | 仅视图 |
\ds | 仅序列 |
\dn | 模式 |
\du/\dg | 角色 |
\df | 函数 |
\dx | 已安装扩展 |
\dT | 数据类型 |
\db | 表空间 |
这些命令都支持模式匹配。\dt int\*会显示所有以int开头的表;\dt *.*则列出所有模式下的表。
查看配置参数(PG 16+)
\dconfig-- 仅显示非默认值的参数\dconfig shared*-- 显示所有以 shared 开头的参数\dconfig*-- 显示全部参数\dconfig+work_mem-- 附带类型、上下文、权限信息\dconfig是 PostgreSQL 16 引入的命令,比SHOW更灵活——支持通配符模式,不用精确记住参数名。
三、格式化与效率:让输出更易读,让操作更快
\timing:显示执行耗时
\timing-- 切换开关\timingon-- 开启\timingoff-- 关闭开启后,每条 SQL 执行完毕都会在结果下方显示耗时(毫秒级)。这是日常开发中最实用的元命令之一——你能立刻感受到索引是否生效、查询是否变慢。
\x:扩展显示,宽表救星
\x-- 切换开关\x auto-- 自动模式:窄结果用表格,宽结果用扩展格式当查询返回的列很多时,默认的表格输出会折行得惨不忍睹。\x把每行数据转成“列名 | 值”的纵向格式,一条记录一目了然。\x auto是更聪明的选择,psql 会根据结果宽度自动决定是否使用扩展格式。
\pset null:让 NULL 可见
默认情况下,psql 无法区分 NULL 和空字符串。设置一个可见的 NULL 标记:
\psetnull'(null)'之后所有 NULL 值都会显示为(null),空字符串则显示为空白。
\watch:重复执行查询
\watch5-- 每 5 秒执行一次上一条查询\watch i=5c=10-- 每 5 秒执行,共执行 10 次\watch重复执行当前查询缓冲区中的查询,默认间隔 2 秒。它和\timing配合,可以在 psql 里搭建一个简易的监控面板:
SELECTcount(*)FROMordersWHEREstatus='pending';\timingon\watch10每 10 秒刷新一次待处理订单数,同时显示查询耗时。PostgreSQL 16 起支持\watch 0(无延迟),但需注意客户端 CPU 消耗。
\e:用编辑器写 SQL
\e-- 用 $EDITOR 打开上一条查询进行编辑\e filename.sql-- 编辑指定文件在编辑器里写复杂的多表 JOIN 或 CTE,比在 psql 里一行行敲高效得多。保存退出后,psql 会自动执行编辑后的 SQL。
\s:查看命令历史
\s-- 显示历史命令\s/tmp/history-- 保存到文件\s显示当前会话的命令历史,方便回顾刚才执行了哪些操作。配合~/.psqlrc配置文件,可以在每次启动 psql 时自动设置常用参数,比如\timing on、\pset null '(null)'、\x auto。
四、数据导入导出:\copy 与 COPY 的本质区别
这是 psql 中最容易被混淆的知识点。
COPY是 SQL 命令,在服务器端执行,读写的是服务器文件系统上的文件,权限取决于 postgres 进程的操作系统用户。
\copy是 psql 元命令,在客户端执行,读写的是你本地机器上的文件,权限取决于你当前的用户。
换句话说:如果你在本地机器上有一个 CSV 文件要导入远程数据库,必须用\copy;如果你要导出数据到服务器上的某个路径,用COPY。
\copy 的常用形式
-- 导出查询结果到本地 CSV\copy(SELECT*FROMusersWHEREcreated_at>'2026-01-01')TO'/tmp/users.csv'WITHCSV HEADER-- 从本地 CSV 导入\copy usersFROM'/tmp/users.csv'WITHCSV HEADER\copy会自动把数据通过客户端/服务器连接传输,底层调用的是COPY FROM STDIN或COPY TO STDOUT。注意:由于数据要经过客户端中转,\copy的效率略低于服务器端COPY,但对于日常导入导出完全够用。
五、性能排查:psql 能做的比你想的多
psql 不只是执行 SQL 的地方,它也是排查性能问题的第一现场。
查看当前活跃查询
SELECTpid,usename,application_name,now()-query_startASduration,state,wait_event_type,wait_event,queryFROMpg_stat_activityWHEREstate!='idle'ANDpid<>pg_backend_pid()ORDERBYdurationDESC;pg_stat_activity是排查阻塞、长事务、连接泄漏的起点。重点关注state为active且duration很大的查询,以及state为idle in transaction的会话——后者往往意味着应用忘记提交或回滚,持续持有锁。
查看锁等待
SELECTblocked_locks.pidASblocked_pid,blocking_locks.pidASblocking_pid,blocked_activity.queryASblocked_query,blocking_activity.queryASblocking_queryFROMpg_locks blocked_locksJOINpg_locks blocking_locksONblocking_locks.locktype=blocked_locks.locktypeANDblocking_locks.databaseISNOTDISTINCTFROMblocked_locks.databaseANDblocking_locks.relationISNOTDISTINCTFROMblocked_locks.relationANDblocking_locks.pageISNOTDISTINCTFROMblocked_locks.pageANDblocking_locks.tupleISNOTDISTINCTFROMblocked_locks.tupleANDblocking_locks.virtualxidISNOTDISTINCTFROMblocked_locks.virtualxidANDblocking_locks.transactionidISNOTDISTINCTFROMblocked_locks.transactionidANDblocking_locks.classidISNOTDISTINCTFROMblocked_locks.classidANDblocking_locks.objidISNOTDISTINCTFROMblocked_locks.objidANDblocking_locks.objsubidISNOTDISTINCTFROMblocked_locks.objsubidANDblocking_locks.pid!=blocked_locks.pidJOINpg_stat_activity blocked_activityONblocked_activity.pid=blocked_locks.pidJOINpg_stat_activity blocking_activityONblocking_activity.pid=blocking_locks.pidWHERENOTblocked_locks.granted;这个查询直接告诉你谁在阻塞谁,以及双方在执行什么 SQL。
查看最耗时的 SQL(需 pg_stat_statements)
SELECTquery,calls,total_exec_time,mean_exec_time,rowsFROMpg_stat_statementsORDERBYtotal_exec_timeDESCLIMIT10;pg_stat_statements是性能排查的必备扩展。按total_exec_time排序,能找到“总耗时最高”的 SQL;按mean_exec_time排序,能找到“单次最慢”的 SQL。两种维度各有用途:前者适合优化高频查询,后者适合优化单点慢查询。
用 \watch 实时监控
SELECTcount(*)FROMpg_stat_activityWHEREstate='active';\watch5一个极简的实时监控:每 5 秒刷新一次活跃查询数。如果这个数字持续偏高,说明数据库正在承受较大压力。
六、总结
psql 的核心能力可以归纳为五组:
| 类别 | 关键命令 | 用途 |
|---|---|---|
| 连接 | 连接字符串、~/.pgpass | 安全、灵活地连接 |
| 信息查询 | \l、\c、\d、\dt、\di、\dconfig | 摸清数据库全貌 |
| 格式化 | \timing、\x、\pset null | 提升可读性 |
| 效率 | \e、\s、\watch | 加速日常操作 |
| 数据与排查 | \copy、pg_stat_activity、pg_stat_statements | 导入导出与性能诊断 |
一句话:psql 不是“没有图形界面所以将就用”,而是“因为没有图形界面所以更快”。把~/.psqlrc配好,把\timing、\x auto、\pset null设成默认,你会发现命令行才是 PostgreSQL 最舒服的工作方式。
下一篇,我们聊聊 pgAdmin 和 DBeaver:图形化工具适合什么场景,怎么用它们管理数据库、查看执行计划,以及如何避免在生产环境误操作。
思考题:
你平时用 psql 还是图形化工具?有没有用\watch做过实时监控,或者用pg_stat_activity定位过阻塞?欢迎在评论区分享你的 psql 使用习惯。