很多开发者进入 PostgreSQL 后,先熟悉的是 SELECT、INSERT 和 ALTER TABLE。但在交互式终端 psql 中,还有一组不属于 SQL、以反斜杠开头且通常不需要分号的元命令。它们由 psql 客户端处理,可以快速查看数据库结构、调整输出格式、执行脚本和导入导出数据,是 DBA 与后端开发者日常排查问题的重要工具。
元命令与 SQL 的边界
SQL 会被发送给 PostgreSQL 服务器执行;元命令则主要控制当前 psql 会话,或者根据系统目录生成查询。最直观的区别是语法:
SELECT current_database();
\conninfo
第一行是 SQL,需要以分号结束。第二行是元命令,由 psql 直接解释,不需要分号。
遇到不熟悉的命令时,可以直接在终端中查帮助:
\? -- 列出 psql 元命令
\? describe -- 搜索描述对象相关的元命令
\h -- 列出 SQL 命令帮助
\h CREATE TABLE -- 查看 CREATE TABLE 语法
这里有一个容易混淆的细节:\? 查询的是 psql 元命令,\h 查询的是 PostgreSQL SQL 语法。排查问题时分清这两层,能少翻很多文档。
用几条命令摸清陌生数据库
接手一个数据库时,不必立刻手写查询系统目录。下面这组命令通常足以完成第一轮勘察:
\conninfo -- 显示当前连接信息
\l -- 列出数据库
\dn -- 列出 schema
\dt -- 列出当前搜索路径中的表
\dt *.* -- 列出所有可见 schema 中的表
\dv -- 列出视图
\di -- 列出索引
\df -- 列出函数
\d public.orders -- 查看表、视图或其他关系对象的定义
\d+ public.orders -- 显示更详细的信息
对象模式支持通配符,因此数据库很大时,可以缩小搜索范围:
\dt public.order*
\df public.calculate_*
\d 的价值不只是列出字段。针对表执行时,它通常还会展示字段类型、默认值、索引和约束等信息;\d+ 会提供更多细节。实际可见内容可能随 PostgreSQL 与 psql 版本变化,因此自动化程序不应解析这类面向人的输出,稳定集成仍应查询系统目录或 information_schema。
让查询结果更适合阅读和排查
宽表在默认表格布局下很难阅读。\x 可以切换扩展显示,让每条记录按字段纵向展开:
\x on
SELECT * FROM pg_stat_activity WHERE state <> 'idle';
\x off
也可以让 psql 根据结果宽度自动选择布局:
\x auto
分析慢查询或比较改动前后的耗时时,打开客户端计时:
\timing on
SELECT count(*) FROM orders;
\timing off
这里显示的是客户端观察到的执行时间,可能包含网络传输和结果处理成本。要研究执行计划,仍需使用 EXPLAIN (ANALYZE, BUFFERS),并注意 ANALYZE 会真实执行语句。
持续观察指标时,\watch 可以按固定间隔重复上一条查询。例如在测试环境中每两秒查看活动连接数:
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state
ORDER BY state;
\watch 2
按 Ctrl+C 停止刷新。生产环境中应控制查询成本与刷新频率,避免监控查询本身制造额外负载。
一套可以直接改造的日常工作流
下面的示例假设本机已经安装 psql,并且可通过环境变量连接数据库。运行前请替换连接参数;不要把生产密码直接写入脚本,可使用 .pgpass、受控环境变量或团队现有的凭据管理工具。
export PGHOST=127.0.0.1
export PGPORT=5432
export PGDATABASE=app_db
export PGUSER=app_user
psql
进入会话后,可以这样完成结构检查、计时和结果导出:
\set ON_ERROR_STOP on
\conninfo
\dt public.*
\d+ public.orders
\timing on
\x auto
SELECT id, status, created_at
FROM public.orders
ORDER BY created_at DESC
LIMIT 20;
\copy (
SELECT id, status, created_at
FROM public.orders
WHERE created_at >= CURRENT_DATE
) TO './orders_today.csv' WITH (FORMAT csv, HEADER true)
这里使用的是 \copy,文件由运行 psql 的客户端读写;SQL 的 COPY 通常由数据库服务器读写文件,涉及服务器文件系统路径与权限。远程连接数据库时,这个区别尤其重要。
已有 SQL 文件可以通过 \i 在当前会话执行:
\i ./reports/daily_orders.sql
也可以从 Shell 执行,并让脚本遇到 SQL 错误后立即失败:
psql \
--set=ON_ERROR_STOP=on \
--file=./reports/daily_orders.sql
需要把输出写入文件时,可以临时重定向:
\o ./query-output.txt
SELECT now(), current_database(), current_user;
\o
第二个不带参数的 \o 会恢复标准输出。操作完成后及时恢复,避免后续查询结果继续写入文件而让终端看起来没有响应。
纳入习惯前的检查清单
日常使用可以先记住 \?、\d、\dt、\x、\timing、\copy 和 \i。这几条覆盖了帮助查询、结构探索、结果阅读、性能观察、数据交换和脚本执行。
元命令适合人机交互和运维脚本,但也有边界:不同版本的显示格式可能变化;\watch 可能反复执行高成本查询;\copy 会在客户端机器读写数据;脚本如果没有启用 ON_ERROR_STOP,发生错误后仍可能继续运行。正式自动化前,应固定客户端版本、限制数据库权限,并让错误能够可靠地传递给 CI 或任务调度器。
真正节省时间的不是背下全部命令,而是把常见动作缩短:用 \d 代替临时拼系统目录查询,用 \x auto 处理宽结果,用 \copy 明确客户端文件边界,再用 ON_ERROR_STOP 让脚本失败得足够清楚。