psql 输出格式(\pset)
在《psql 入门》里我们只把 psql 当成「敲 SQL 的地方」,它默认的表格输出已经足够好用。但当你开始用 psql 做日常巡检、脚本化取数、生成报表、把查询结果喂给下游程序时,「默认表格」就会显得不够用:列太宽被压缩、NULL 显示为空白看不清、想直接产出 CSV 或 HTML 却不知道从哪下手。\pset 就是解决这一切的钥匙——它是 psql 内置的「输出格式化控制台」,几乎决定了每一次查询结果最终长什么样、去了哪里。
\pset 的能力覆盖四个层面:格式(aligned、csv、html 等十来种输出格式)、外观(边框、线型、分隔符、NULL 占位、是否显示行数统计)、布局(普通表格还是纵向扩展显示、分页器何时介入)与去向(输出到终端、文件还是管道)。它既可以通过 \pset 选项 值 精确设置,也有 \x、\H、\a、\t、\o 这类快捷元命令做一键切换。理解了这一页,你会把 psql 从「交互式终端」升级成「可编程的报表引擎」——后面几页的变量、事务与 \copy,也都建立在这个基础上。
需要提前说明的是:\pset 改变的是 psql 客户端的展示行为,它不改变服务器返回的数据本身。因此它对性能没有影响、对数据没有副作用,你可以放心地在任何会话里反复试验。
前置知识
建议先阅读:pg_upgrade 升级
基础概念
psql 处理查询结果的流程可以概括为一条「三段式流水线」:
SQL 查询 ──► 服务器返回结果集 ──► psql 格式化层(\pset 状态) ──► 输出目的地
│
format / border / expanded / null / pager …
│
stdout / \o 文件 / 管道 / \g file- 格式化层由一组
\pset状态项构成。每个状态项都有默认值,会话内可以随时修改,且只影响本会话——你在 psql 里设置的格式不会影响其他用户,也不会写进数据库。 - 输出目的地默认是标准输出(终端),可以通过
\o 文件或\g 文件重定向,也可以用\o | 命令直接送进管道。 - 快捷元命令是
\pset的别名或组合键,例如\x等价于切换expanded,\t等价于切换tuples_only。
| 状态项 | 快捷命令 | 作用 |
|---|---|---|
format | \a(aligned/unaligned 切换)、\H(HTML 切换) | 选择输出格式 |
border | — | 表格边框数量 |
expanded | \x | 纵向(每行一块)显示 |
linestyle | — | 边框线型:ascii / old-ascii / unicode |
null | — | NULL 值显示为什么字符串 |
fieldsep / recordsep | \f(fieldsep) | 列分隔符 / 行分隔符 |
footer | — | 是否显示 (n rows) 统计行 |
tuples_only | \t | 只输出数据行,省去表头等装饰 |
pager | — | 何时调用分页器 |
numericlocale | — | 是否按本地化显示千分位 |
tableattr | \T | HTML 输出时 <table> 标签的属性 |
title | \C | 表格标题(HTML/某些格式下显示) |
columns | — | wrapped 格式的目标宽度,并影响分页判断 |
\pset 与 COPY 的边界
初学者常把 \pset format csv 与 \copy 混为一谈,这里先把边界划清:
\pset format csv(配合\o或\g)是 psql 把查询结果「打印」成 CSV——它走的是结果集格式化层,数据先完整地经过 psql。\copy是 数据搬运命令——它利用服务器的COPY协议把数据流式地送进或送出文件,不经过格式化层,速度远快于「打印」。
导出少量结果给人看或给程序用,用 \pset 足够;导出大批量数据(几万行以上),用 \copy。两者的组合拳在后面《psql \copy 数据导入导出》一页详细展开。
输出流的三种消费方
\pset 调什么参数,取决于结果最终给谁看。把消费方分成三类,设置策略一目了然:
| 消费方 | 特征 | 推荐设置 |
|---|---|---|
| 人(交互终端) | 需要可读性、容错性 | expanded auto + linestyle unicode + null '[NULL]' + pager |
| 程序(脚本/管道) | 需要稳定契约、可解析 | unaligned 或 csv + tuples_only on + footer off |
| 文件/报表(归档交付) | 需要自描述、可交付 | csv 或 html + title + header,配 \o |
「人」的设置放 .psqlrc;「程序」的设置写死在脚本里(且 -X 屏蔽 .psqlrc);「文件/报表」的设置按交付物要求在脚本中显式切换。三套设置相互独立,是一条 psql 会话里随时可切换的「输出人格」——切换成本只有一条 \pset,这正是把状态机设计成会话级的好处。
语法与用法
\pset 的通用语法是:
\pset [ option [ value ] ]- 省略
option:列出当前所有格式化设置; - 省略
value:对布尔型选项做取反切换(例如\pset expanded在开/关之间切换),对枚举型选项则循环切换或报错; - 传入
value:精确设置。布尔值接受on/off/true/false/1/0。
-- 查看当前全部设置
\pset
-- 设置格式为 CSV
\pset format csv
-- 扩展显示自动模式(列太多放不下时自动纵向展示)
\pset expanded auto
-- NULL 显示为 <NULL>
\pset null '<NULL>'与 \pset 对应的快捷元命令一览:
\a -- 在 aligned 与 unaligned 之间切换
\H -- 在当前输出格式与 HTML 之间切换
\t -- 切换 tuples_only(只显示数据行)
\x -- 切换 expanded 显示
\f '|' -- 设置 unaligned 格式的字段分隔符
\C '报表标题' -- 设置表格标题(第三个 C 大写)
\T 'class=xl' -- 设置 HTML <table> 标签属性
\o 'out.txt' -- 后续输出重定向到文件;不带参数则恢复终端输出重定向的两条路径:
-- 路径一:\g file —— 只把「当前缓冲区里这条查询」的结果写入文件,一次性
SELECT now() \g /tmp/now.txt
-- 路径二:\o file —— 从现在起「所有」输出都进入文件,直到再次执行 \o
\o /tmp/session.txt
SELECT version();
SELECT now();
\owatch 定时重复执行当前查询缓冲区:
SELECT pid, wait_event_type, query FROM pg_stat_activity WHERE state <> 'idle' \watch 5详细说明
格式家族:从 aligned 到 asciidoc
\pset format 的官方取值包括 aligned、unaligned、wrapped、csv、html、asciidoc、latex、latex-longtable、troff-ms。同一个结果集在不同格式下的样子差异巨大:
CREATE TABLE demo (id int, name text, val numeric);
INSERT INTO demo VALUES (1, 'alpha', 1234.5), (2, NULL, 7.25);aligned(默认)——人类可读的对齐表格:
id | name | val
----+-------+--------
1 | alpha | 1234.5
2 | | 7.25
(2 rows)unaligned——每行一条记录,用字段分隔符(默认 |)连接,行内不换行,最贴近「原始数据流」,常用于脚本:
1|alpha|1234.5
2||7.25wrapped——在 aligned 基础上,超宽的列会折行显示,配合 columns 指定目标宽度,适合查看超长的 JSON、SQL 或日志列:
id | name | val
----+----------+--------
1 | alpha | 1234.5
2 | | 7.25csv——标准 CSV 输出,含引号转义处理,与 psql --csv 启动选项等价:
id,name,val
1,alpha,1234.5
2,,html——完整的 HTML 片段,配合 \o 可以直接产出可浏览的报表页:
<table border="1">
<tr>
<th align="right">id</th>
<th align="left">name</th>
...asciidoc / latex / latex-longtable / troff-ms——面向文档排版工具链的标记语言输出,写 AsciiDoc 文档、LaTeX 论文或 troff 手册时可以直接嵌入。
关于 json 格式
不少资料(包括一些旧版教程)提到 \pset format json,但截至目前的官方文档,\pset format 并未收录 json 这一取值,请以你所使用版本的官方文档为准。想在 psql 里获得 JSON 输出,可靠的做法是让 SQL 自己负责序列化:
SELECT json_agg(t) FROM (SELECT id, name, val FROM demo) AS t;
SELECT row_to_json(t) FROM demo AS t LIMIT 1;边框、线型与列宽
border 控制边框的丰富程度,数值越大边框越多:
border 0:无边框(aligned 下连列间分隔线都消失);border 1:默认值,仅内部分隔线;border 2:内部 + 外部边框。
\pset border 2
SELECT * FROM demo;+----+-------+--------+
| id | name | val |
+----+-------+--------+
| 1 | alpha | 1234.5 |
| 2 | | 7.25 |
+----+-------+--------+linestyle 决定画线用的字符,三个取值各有味道:
| 取值 | 效果 | 场景 |
|---|---|---|
ascii | 纯 ASCII 字符(+、-、|) | 默认,兼容性最好 |
old-ascii | 旧版风格,扩展模式下用 : 与 ; 分隔 | 兼容老脚本 |
unicode | ┌─┬┐ │ 等框线字符 | 终端字体支持时更美观 |
\pset linestyle unicode
\pset border 1┌────┬───────┬────────┐
│ id │ name │ val │
├────┼───────┼────────┤
│ 1 │ alpha │ 1234.5 │
│ 2 │ ∅ │ 7.25 │
└────┴───────┴────────┘columns 设置 wrapped 格式的目标宽度,同时参与「结果会不会超过终端宽度、要不要唤起 pager」的判断。不设置时 psql 用 COLUMNS 环境变量或查询终端获得宽度;在无终端的脚本环境里,宽度判断会退化为「不分页」。
扩展显示 \x 与 expanded auto
默认的 aligned 表格是「一行一记录、一列一竖条」。当表很宽(例如 pg_stat_activity 有 30 多列)时,每个单元格会被压到几个字符宽,完全没法读。expanded 把布局翻转成「一行记录占一块,一行一个字段」:
\pset expanded on
SELECT * FROM demo WHERE id = 1;-[ RECORD 1 ]------
id | 1
name | alpha
val | 1234.5expanded 有三态:on、off、auto。auto 是最值得推荐的日常设置——列少时保持表格,列多放不下时自动转纵向,两头兼顾:
\pset expanded auto快捷命令 \x 等价于对 expanded 做开关切换;\x auto、\x on、\x off 也都合法。
NULL 显示、tuples_only 与 footer
数据库里的 NULL 与空字符串是两回事,但默认输出里两者都是空白,肉眼根本分不开。null 选项给 NULL 一个专属记号:
\pset null '[NULL]'
SELECT * FROM demo; id | name | val
----+--------+--------
1 | alpha | 1234.5
2 | [NULL] | 7.25
(2 rows)tuples_only(快捷键 \t)关掉表头、行数统计等所有「装饰」,只留纯数据行——写脚本时与 unaligned 搭配堪称黄金组合:
\pset tuples_only on
\pset format unaligned
SELECT id, name FROM demo ORDER BY id;1|alpha
2|footer 单独控制 (n rows) 这一行。生成 CSV/报告时通常关掉它,避免最后一行混入统计信息:
\pset footer off分隔符定制:fieldsep 与 recordsep
fieldsep 只对 unaligned 格式生效,默认是 |。导出制表符分隔(TSV,Excel 可直接粘贴)或分号分隔(欧洲 Excel 的语言习惯)文件时很有用:
\pset format unaligned
\pset fieldsep '\t'
SELECT id, name FROM demo;1 alpha
2配套的 fieldsep_zero 把分隔符换成 NUL 字节,配合 xargs -0 等工具处理「内容里什么怪字符都可能出现」的数据。recordsep 与 recordsep_zero 则控制行与行之间的分隔(默认换行符),极少改动但了解即可。
快捷命令 \f 等价于设置 fieldsep:\f ','。
pager 与 numericlocale
结果超过一屏时 psql 会调用外部分页器(less 等)翻页,这在交互时方便,在脚本里却是灾难——输出可能被卡在分页器里没人按空格。pager 三个取值:
| 取值 | 行为 |
|---|---|
off | 永不使用分页器 |
on(默认) | 输出超出终端高度且终端可用时使用 |
always | 无论是否超屏都使用 |
脚本环境的经典写法是环境变量与 \pset 双保险:
export PSQL_PAGER='less -S' # 横向不折行,宽表利器;也可用 PAGER
psql -P pager=off -c 'SELECT * FROM big_table' > result.txtPSQL_PAGER 优先于 PAGER,两者都可以带参数(如 less -S)。numericlocale 则控制对齐格式里是否按本地化习惯给数字加千分位分隔符(如 1.234,5),做财务报表时有感,平时保持默认 off。
输出重定向:\g file 与 \o
两条重定向路径的语义差异是本页最容易混淆的点:
| 命令 | 生效范围 | 典型用途 |
|---|---|---|
\g 文件 | 只对当前查询缓冲区这一次执行生效 | 偶尔把某条结果存档 |
\g | 命令 | 当前查询结果通过管道送给外部命令 | \g | gzip > /tmp/r.gz |
\o 文件 | 持续重定向所有输出,直到裸 \o 关闭 | 批量生成一份完整报告 |
\o | 命令 | 后续输出持续进入管道 | \o | mailx -s report dba@example.com |
\o 期间,连 \d 元命令的输出、错误信息都会进入目标文件,这对「生成完整巡检报告」是优点,对「只想导数据」则是陷阱——记得把 footer、\t 等装饰先处理好。
\o /tmp/report.html
\pset format html
\pset title '慢查询 TOP 20'
SELECT pid, now() - query_start AS dur, left(query, 80) AS query
FROM pg_stat_activity
WHERE state <> 'idle'
ORDER BY dur DESC
LIMIT 20;
\o
\pset format aligned表格标题、HTML 属性与剩余选项
前文覆盖了日常 90% 的场景,剩下几个选项在特定场合各显其能:
-- title:给表格一个标题(aligned 下显示在表格上方,HTML 下渲染为 <caption>)
\pset title '活跃会话巡检'
SELECT pid, usename, state FROM pg_stat_activity LIMIT 3;活跃会话巡检
pid | usename | state
------+---------+--------
1201 | app_rw | active
1202 | etl | idle
(2 rows)tableattr(快捷命令\T):HTML 格式下给<table>标签追加属性,如\pset tableattr 'class="data-table" id="sess"',产出物可直接嵌入有样式的页面;columns:wrapped 格式的目标宽度与分页判断依据,宽终端看宽表时显式设置\pset columns 160比 auto 检测更稳;fieldsep_zero/recordsep_zero:以 NUL 作分隔,配合xargs -0消费「内容里什么都有」的数据;unicode_border_linestyle/unicode_column_linestyle/unicode_header_linestyle:linestyle=unicode 时三类框线的细分子风格(single/double),装饰控的最爱;border在 unaligned 下的行为:非零 border 会让 unaligned 输出在行间加分隔行为,具体表现依版本而异,脚本里保持默认 0 即可。
这些选项共同特点是「低频但救命」——写报告、做演示、对接挑剔的下游时,知道自己手里有这些旋钮,比记住每个默认值重要得多。
\gdesc:不执行也能看列结构
\g 家族还有一个常被忽略的成员:\gdesc 显示当前查询缓冲区的列名与类型,但不执行查询:
SELECT pid,
usename,
now() - query_start AS duration,
pg_size_pretty(pg_total_relation_size('orders')) AS table_size
\gdesc Column | Type
-----------+---------------------------
pid | integer
usename | name
duration | interval
table_size| text写长查询时先 \gdesc 验证别名与类型,再决定是否真正执行——对开销大的查询(重聚合、跨库 JOIN 的 FDW)非常实用,也让上一页变量篇「列名即变量名」的 \gset 前置检查有了工具。
\pset format csv 与 \copy 的组合拳
把查询结果落成 CSV 文件,有两条可用的路径,适用场景不同:
路径 A:格式化导出(\pset format csv + \o)
\pset format csv
\pset footer off
\o /tmp/orders.csv
SELECT id, status, amount, created_at FROM orders WHERE created_at >= '2026-09-01';
\o
\pset format aligned- 优点:所见即所得,SELECT 里怎么写、文件里就是什么,支持任意复杂查询(含 JOIN、聚合、表达式列名);
- 缺点:数据先完整地经过 psql 的格式化层,几十万行以上明显偏慢。
路径 B:协议级导出(\copy)
\copy (SELECT id, status, amount, created_at FROM orders WHERE created_at >= '2026-09-01') TO '/tmp/orders2.csv' WITH (FORMAT csv, HEADER true)- 优点:流式传输,快一个数量级;
- 缺点:写法上是一条
\copy命令,长 SQL 塞在括号里不够优雅;列名直接取自 SELECT 输出。
经验法则:几百行以内的「报表级」导出用路径 A(尤其需要 HTML/标题等装饰时);上万行的「数据级」导出必须用路径 B。两者也可以混用:先用 \o+format csv 调试查询、确认结果正确,再把同一段 SELECT 换进 \copy 里放量导出。
\watch:定时观察同一查询
\watch [秒数] 会反复执行当前查询缓冲区里的 SQL,默认每 2 秒一次,Ctrl+C 停止。它是 psql 内置的「简易监控循环」,配合 \pset expanded auto 观察宽视图尤其舒服:
SELECT count(*) AS active,
count(*) FILTER (WHERE wait_event_type IS NOT NULL) AS waiting
FROM pg_stat_activity
WHERE state <> 'idle'
\watch 5 active | waiting
--------+---------
7 | 1
(1 row)
等待 5 秒后自动重复……PostgreSQL 18 放宽了 \watch 的最小间隔限制(最短可到毫秒级),并支持 min_interval 等选项,做亚秒级观测前请查阅所用版本的文档。要注意 \watch 期间客户端会一直「发查询-收结果」空转,对服务器有轻微压力,不适合在生产主库上高频运行;长时间监控请交给专业的监控系统。
.psqlrc 持久化与 PSQLRC、PSQL_PAGER
每次都手敲 \pset 终究麻烦。psql 启动时会自动读取用户的启动文件,把个性化设置持久化:
- Linux/macOS:
~/.psqlrc(环境变量PSQLRC可改路径); - Windows:
%APPDATA%\postgresql\psqlrc.conf。
文件内容就是一串普通的 psql 元命令:
-- ~/.psqlrc
\pset null '[NULL]'
\pset expanded auto
\pset linestyle unicode
\pset footer off
\set ON_ERROR_STOP on
\set PROMPT1 '%n@%M:%>/ %R%# '
\timing on几个必须知道的细节:
-X(或--no-psqlrc)跳过启动文件。写脚本时务必加上:psql -X ...,避免用户个人配置污染脚本行为——尤其是\pset format、\pset null这类会改变输出契约的设置。PGOPTIONS与启动文件的分工:.psqlrc管客户端展示,服务器端的会话参数(如statement_timeout)也可以在.psqlrc里用SET语句设置,但脚本里同样建议用-c 'SET ...'显式声明。- PSQL_PAGER 决定
\pset pager调用哪个分页器,常见配置export PSQL_PAGER='less -S'(-S表示长行不折行,配合宽表、横向滚动查看)。 .psqlrc里写--注释是合法的,psql 会原样执行文件中的每一行元命令与 SQL。
实战示例
示例一:一条命令导出 Excel 友好的 CSV
psql -X -d appdb -v ON_ERROR_STOP=1 <<'SQL'
\pset format csv
\pset footer off
\pset null ''
\o /tmp/daily_summary.csv
SELECT date_trunc('day', created_at)::date AS day,
status,
count(*) AS cnt,
round(sum(amount), 2) AS amount
FROM orders
WHERE created_at >= current_date - interval '7 days'
GROUP BY 1, 2
ORDER BY 1, 2;
\o
SQL要点:-X 屏蔽个人启动文件保证输出契约稳定;\pset null '' 让 NULL 落成空单元格(Excel 里显示为空白而非 [NULL] 字样)。
示例二:生成可发送的 HTML 巡检报告
psql -X -d appdb <<'SQL' > /tmp/inspect.html
\pset format html
\pset border 2
\pset title '数据库巡检报告 - 生成时间见下行'
SELECT now() AS generated_at;
\pset title '活跃会话'
SELECT pid, usename, application_name, state, wait_event_type
FROM pg_stat_activity WHERE state <> 'idle';
\pset title '最大的 10 张表'
SELECT relname,
pg_size_pretty(pg_total_relation_size(relid)) AS total_size
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 10;
SQL一条 psql 会话产出一份含多个表格的完整 HTML,浏览器直接打开即可转发。
示例三:\watch 观察锁等待
\pset expanded auto
SELECT blocked.pid AS blocked_pid,
blocked.wait_event_type,
blocking.pid AS blocking_pid,
left(blocking.query, 60) AS blocking_query
FROM pg_stat_activity blocked
JOIN pg_stat_activity blocking
ON blocking.pid = pg_blocking_pids(blocked.pid)[1]
WHERE blocked.wait_event_type = 'Lock'
\watch 3Ctrl+C 退出观察。若想保留观察轨迹,先 \o /tmp/lock_watch.log 再 \watch。
示例四:一份团队通用的 .psqlrc
-- ~/.psqlrc —— 交互体验向配置,脚本请始终使用 psql -X
\pset null '[NULL]'
\pset expanded auto
\pset linestyle unicode
\pset footer off
\pset pager on
\timing on
\set ON_ERROR_STOP on
\set QUIET on
-- 默认提示符:用户@主机:端口 库名
\set PROMPT1 '%n@%M:%> %~ %# '
\set PROMPT2 ' %R '
-- 常用变量
\set act 'SELECT pid, state, wait_event_type, left(query,60) FROM pg_stat_activity WHERE state <> ''idle'';'
\set locks 'SELECT * FROM pg_locks WHERE NOT granted;'
\set size 'SELECT pg_size_pretty(pg_database_size(current_database())) AS db_size;'配置后,交互会话里直接敲 :act 就能查活跃会话(SQL 里插值用法见下一页《psql 变量与 \gset》)。
注意事项
\pset 只影响展示,不影响数据。 它不会改变查询计划、不会改变返回值本身,但会改变「人从终端上看到什么」。排查问题时如果发现「终端里明明有值、程序里却是 NULL」,先检查 \pset null 是否被启动文件改过。
脚本必须用 -X 隔离 .psqlrc。 用户启动文件里的 \pset format csv、\pset null、\t 都会改变脚本输出格式。所有自动化脚本一律 psql -X,让行为只由命令行参数决定,这是可重复性的底线。
\o 会吞掉错误与元命令输出。 \o 文件 期间错误信息也进文件,脚本里可能「明明失败了却没人发现」。结合 -v ON_ERROR_STOP=1 使用,失败立即退出。
unaligned 的 fieldsep 不做转义。 如果字段值本身含 |,输出会错位。给程序消费的数据请用 format csv(有标准引号转义)或 \copy,不要用裸的 fieldsep。
pager 会让脚本挂住。 在自动化环境(CI、cron)里若终端检测异常,输出可能进入等待输入的分页器。脚本内显式 \pset pager off,或环境里 export PSQL_PAGER=cat 兜底。
watch 不是监控替代品。 \watch 单连接串行轮询,间隔过小会对服务器形成持续压力,也无法告警、无历史曲线。生产监控交给 Prometheus + postgres_exporter 这类方案(详见监控章节),\watch 用于人工临时观察。
宽表优先 expanded auto 而不是调 border。 遇到看不清的宽表,先 \x auto,多数情况立刻可读;盲目加大终端宽度或调边框解决不了问题。
Windows 下的启动文件名不同。 是 %APPDATA%\postgresql\psqlrc.conf 而非 .psqlrc,网上照抄 Linux 路径无效;另外 Windows 控制台的默认代码页可能导致 unicode 线型乱码,此时回退 \pset linestyle ascii。
\pset 的选项名与取值要原样核对。 手滑写成 \pset expand on(少了 ed)会静默创建一个无意义的用户变量而不是报错;关键的输出脚本建议在开头 \echo 当前的 \pset 状态快照,留档可查。
title/tableattr 只影响「有表格语义」的格式。 在 unaligned/csv 下设置标题不会有任何效果;想要「CSV 也带一行说明」只能自己在 \o 里 echo,别指望格式层代劳。
最佳实践
- 在 ~/.psqlrc 里固化三件套:
\pset null '[NULL]'、\pset expanded auto、\pset linestyle unicode。 这三项显著提升日常可读性,且不影响任何脚本(脚本都带-X)。 - 交互用 expanded auto,导出用 csv/copy。 形成肌肉记忆后,「看数据」与「搬数据」两条路径互不干扰。
- 给 NULL 定一个显眼的显示记号。 空白与 NULL 的混淆是数据分析里最隐蔽的坑之一,一个
[NULL]记号能避免大量误判。 - 导出 CSV 之前先关 footer、清 null 记号。
\pset footer off+\pset null '',保证文件里只有干净的数据行。 - 脚本一律
psql -X并显式声明所需格式。 让输出格式成为脚本的一部分,而不是用户环境的巧合。 - 用
\o |管道衔接 Unix 工具链。\o | gzip > /tmp/r.gz、\o | column -t -s'|'这类组合让 psql 无缝融入 shell 流水线。 \g file用作「随手存档」,\o用作「成篇报告」。 一次性结果用前者,多查询汇总用后者,用完记得裸\o关闭。- 给分页器配
less -S。 宽表横向滚动远比折行易读,export PSQL_PAGER='less -S'一行环境变量长期受益。 - \watch 观察要设间隔、要会退出。 3~10 秒的间隔足够大多数排障场景;观察锁等待时注意
\watch本身也可能被阻塞视图里的查询影响。 - 把常用巡检 SQL 存成 .psqlrc 变量。 如示例四的
:act、:locks,把重复敲的长查询变成一个短词,这是 psql 效率提升最明显的习惯。 - 文档排版场景直接用 asciidoc/latex 格式。 与其手工把查询结果粘成表格,不如
\pset format asciidoc+\o一键产出,改数后重跑即可。 - 升级 psql 版本后重验脚本输出。 大版本间格式化细节(如 unicode 线型、CSV 转义)偶有微调,核心导出脚本在升级演练时纳入回归清单。
下一节
继续学习:psql 变量与 \gset