PG实战笔记 | 09 PostgreSQL psql客户端基本操作

PG实战笔记 | 09 PostgreSQL psql客户端基本操作

上一篇我们完成了性能参数调优。这一篇,我们聊一个被很多人低估的工具:psql。它看起来只是一个黑底白字的命令行,但真正用熟之后,你会发现它比大多数图形化工具都高效------元命令、变量、脚本、监控,样样都能做。这一篇,我们把 psql 从"连接工具"升级为"运维利器"。

一、连接方式:不止 psql -U postgres

psql 支持多种连接方式,日常开发中最常用的是命令行参数:

bash 复制代码
psql -h localhost -p 5432 -U postgres -d mydb
  • -h:主机地址
  • -p:端口,默认 5432
  • -U:用户名
  • -d:数据库名

但在复杂环境中,参数多了容易记错。更推荐使用 连接字符串:

bash 复制代码
# 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 的情况下摸清数据库全貌。

列出所有数据库

sql 复制代码
\l          -- 列出所有数据库
\l+         -- 附带大小、表空间、描述

\l 是连接后第一个该执行的命令,确认自己连到了正确的数据库。

切换数据库

sql 复制代码
\c mydb          -- 切换到 mydb
\c mydb postgres -- 以 postgres 用户切换到 mydb

查看表结构

sql 复制代码
\d users         -- 查看 users 表的列、索引、约束
\d+ users        -- 附带注释和磁盘大小

\d 不仅显示列名和类型,还会显示索引、主键、外键、触发器、访问权限------基本上是这个表的完整画像。

按对象类型列出

\d 系列有一套完整的变体,按对象类型过滤:

命令 作用
\dt 仅表
\di 仅索引
\dv 仅视图
\ds 仅序列
\dn 模式
\du / \dg 角色
\df 函数
\dx 已安装扩展
\dT 数据类型
\db 表空间

这些命令都支持模式匹配。\dt int\* 会显示所有以 int 开头的表;\dt *.* 则列出所有模式下的表。

查看配置参数(PG 16+)

sql 复制代码
\dconfig              -- 仅显示非默认值的参数
\dconfig shared*      -- 显示所有以 shared 开头的参数
\dconfig *            -- 显示全部参数
\dconfig+ work_mem    -- 附带类型、上下文、权限信息

\dconfig 是 PostgreSQL 16 引入的命令,比 SHOW 更灵活------支持通配符模式,不用精确记住参数名。

三、格式化与效率:让输出更易读,让操作更快

\timing:显示执行耗时

sql 复制代码
\timing          -- 切换开关
\timing on       -- 开启
\timing off      -- 关闭

开启后,每条 SQL 执行完毕都会在结果下方显示耗时(毫秒级)。这是日常开发中最实用的元命令之一------你能立刻感受到索引是否生效、查询是否变慢。

\x:扩展显示,宽表救星

sql 复制代码
\x               -- 切换开关
\x auto          -- 自动模式:窄结果用表格,宽结果用扩展格式

当查询返回的列很多时,默认的表格输出会折行得惨不忍睹。\x 把每行数据转成"列名 | 值"的纵向格式,一条记录一目了然。\x auto 是更聪明的选择,psql 会根据结果宽度自动决定是否使用扩展格式。

\pset null:让 NULL 可见

默认情况下,psql 无法区分 NULL 和空字符串。设置一个可见的 NULL 标记:

sql 复制代码
\pset null '(null)'

之后所有 NULL 值都会显示为 (null),空字符串则显示为空白。

\watch:重复执行查询

sql 复制代码
\watch 5         -- 每 5 秒执行一次上一条查询
\watch i=5 c=10  -- 每 5 秒执行,共执行 10 次

\watch 重复执行当前查询缓冲区中的查询,默认间隔 2 秒。它和 \timing 配合,可以在 psql 里搭建一个简易的监控面板:

sql 复制代码
SELECT count(*) FROM orders WHERE status = 'pending';
\timing on
\watch 10

每 10 秒刷新一次待处理订单数,同时显示查询耗时。PostgreSQL 16 起支持 \watch 0(无延迟) ,但需注意客户端 CPU 消耗。

\e:用编辑器写 SQL

sql 复制代码
\e               -- 用 $EDITOR 打开上一条查询进行编辑
\e filename.sql  -- 编辑指定文件

在编辑器里写复杂的多表 JOIN 或 CTE,比在 psql 里一行行敲高效得多。保存退出后,psql 会自动执行编辑后的 SQL。

\s:查看命令历史

sql 复制代码
\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 的常用形式

sql 复制代码
-- 导出查询结果到本地 CSV
\copy (SELECT * FROM users WHERE created_at > '2026-01-01') TO '/tmp/users.csv' WITH CSV HEADER

-- 从本地 CSV 导入
\copy users FROM '/tmp/users.csv' WITH CSV HEADER

\copy 会自动把数据通过客户端/服务器连接传输,底层调用的是 COPY FROM STDIN 或 COPY TO STDOUT。注意:由于数据要经过客户端中转,\copy 的效率略低于服务器端 COPY,但对于日常导入导出完全够用。

五、性能排查:psql 能做的比你想的多

psql 不只是执行 SQL 的地方,它也是排查性能问题的第一现场。

查看当前活跃查询

sql 复制代码
SELECT pid, usename, application_name,
       now() - query_start AS duration,
       state, wait_event_type, wait_event, query
FROM pg_stat_activity
WHERE state != 'idle'
  AND pid <> pg_backend_pid()
ORDER BY duration DESC;

pg_stat_activity 是排查阻塞、长事务、连接泄漏的起点。重点关注 state 为 active 且 duration 很大的查询,以及 state 为 idle in transaction 的会话------后者往往意味着应用忘记提交或回滚,持续持有锁。

查看锁等待

sql 复制代码
SELECT blocked_locks.pid AS blocked_pid,
       blocking_locks.pid AS blocking_pid,
       blocked_activity.query AS blocked_query,
       blocking_activity.query AS blocking_query
FROM pg_locks blocked_locks
JOIN pg_locks blocking_locks ON blocking_locks.locktype = blocked_locks.locktype
    AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database
    AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
    AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
    AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
    AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
    AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
    AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
    AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
    AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
    AND blocking_locks.pid != blocked_locks.pid
JOIN pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted;

这个查询直接告诉你谁在阻塞谁,以及双方在执行什么 SQL。

查看最耗时的 SQL(需 pg_stat_statements)

sql 复制代码
SELECT query, calls, total_exec_time, mean_exec_time, rows
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

pg_stat_statements 是性能排查的必备扩展。按 total_exec_time 排序,能找到"总耗时最高"的 SQL;按 mean_exec_time 排序,能找到"单次最慢"的 SQL。两种维度各有用途:前者适合优化高频查询,后者适合优化单点慢查询。

用 \watch 实时监控

sql 复制代码
SELECT count(*) FROM pg_stat_activity WHERE state = 'active';
\watch 5

一个极简的实时监控:每 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 使用习惯。

相关推荐
Nturmoils8 小时前
集中式与分布式怎么选:从订单读写看 KingbaseES 的架构边界
数据库
希和20278 小时前
考研英语阅读词汇笔记|城市野径、抄近道步道(非正式小路)
笔记·考研
xiaomuzuirenzhen8 小时前
大专电子商务从事电商运营分析师需要考证吗?
大数据·数据库
翔云12345610 小时前
RocksDB中,客户端每写入一次数据,需要访问几次磁盘
运维·数据库·mysql
DevOpenClub11 小时前
职教高考控制线 API:招生类别枚举、筛选与空分数含义
java·数据库·高考
一个人旅程~11 小时前
关于imac27inch因改短用户名导致混合硬盘和系统崩溃的问题分析与故障解决
经验分享·笔记·macos·新浪微博
心祭丫丫11 小时前
【每天一个 Python 小案例17】Python 实现通讯录
开发语言·人工智能·笔记·python·学习
GeW12 小时前
新质生产力路线图解读:数据库性能优化与Linux调优专场
linux·数据库
派大猩猩_13 小时前
Obsidian 笔记怎么同步多端:Nutstore Sync 大笔记库同步测评
笔记·obsidian·obsidian插件·obsidian同步
在多学一点14 小时前
MYSQL第二次作业
android·数据库·mysql