PostgreSQL 临时表和 UNLOGGED 表有什么区别?适合什么场景?
简化版
临时表只在会话或事务内存在,适合单次任务中转;UNLOGGED 表是持久表但不写 WAL,速度更快,崩溃后会被截断且不能用于可靠复制。临时表偏会话级临时数据,UNLOGGED 表偏可重建的低可靠中间数据。
详细版
临时表常用于复杂报表、批处理、ETL 中间结果。它对当前会话可见,生命周期可配置为事务结束或会话结束。
UNLOGGED 表结构和普通表类似,但数据变更不写 WAL,因此写入压力较低。不过数据库崩溃恢复后,UNLOGGED 表数据可能丢失或被清空。
选择时看数据是否可重建、是否需要崩溃恢复、是否需要复制到从库。核心业务数据不能放 UNLOGGED 表。
完整版教学
一、临时表是什么
临时表用于保存会话内的中间结果。它不会和其他会话共享,名字可以和普通表相同但优先解析到临时 schema。
CREATE TEMP TABLE tmp_user_ids(id bigint) ON COMMIT DROP;
ON COMMIT DROP 表示事务结束就删除;也可以选择保留到会话结束。这适合一次任务里的中间集合。
二、UNLOGGED 表是什么
UNLOGGED 表是数据库里的真实表,但数据修改不写 WAL。少写 WAL 意味着批量写入可能更快,磁盘日志压力更小。
CREATE UNLOGGED TABLE import_staging (
id bigint,
payload jsonb
);
它适合 staging、中间计算、可从源数据重新生成的数据,不适合订单、支付、账户这类核心事实。
三、为什么 UNLOGGED 不可靠
WAL 是 PostgreSQL 崩溃恢复和复制的重要基础。UNLOGGED 表不写 WAL,就不能保证宕机后按日志恢复数据。
如果数据库异常崩溃,UNLOGGED 表在恢复后会被自动截断。也就是说表结构还在,但数据可能没了。
数字例子:你用 UNLOGGED 表导入 500 万条临时数据,导入到 80% 时机器宕机,恢复后这张表可能为空,需要重新导入。
四、临时表和 UNLOGGED 表对比
| 维度 | 临时表 | UNLOGGED 表 |
|---|---|---|
| 生命周期 | 会话或事务 | 持久结构 |
| 可见性 | 当前会话 | 全局可见 |
| WAL | 较少或不记录数据变化 | 不记录数据变化 |
| 崩溃恢复 | 临时数据本来不保 | 数据会丢 |
| 适合场景 | 单次任务中间结果 | 可重建 staging |
两者都不是核心业务持久化的替代品。
五、使用时的工程注意点
临时表过多会给系统 catalog 带来压力,连接池复用场景也要注意清理。事务池模式下,临时表和会话绑定的语义可能让应用踩坑。
UNLOGGED 表要明确标注可重建,最好有重建脚本。导入完成并校验后,正式数据仍应写入普通表。
如果下游依赖逻辑复制或物理备份,也要确认 UNLOGGED 表的数据是否符合预期,因为它的数据可靠性和复制语义不同。
六、常见误区与追问
- 误区:UNLOGGED 表只是更快的普通表。 它牺牲 WAL 保护,崩溃后数据可能丢失。
- 误区:临时表适合跨请求保存状态。 临时表通常绑定会话或事务,不适合业务状态。
- 误区:中间数据都可以放 UNLOGGED。 只有可重建、可丢失的数据才适合。
- 追问:UNLOGGED 表会复制到从库吗? 其数据不按普通 WAL 可靠复制,不能依赖它做高可用数据。
- 追问:什么时候用 staging 表? 批量导入、清洗、校验后再写正式表时很适合。
七、加强记忆
记忆钩子:临时表像草稿纸,用完就扔;UNLOGGED 表像白板,写得快,但断电后内容可能没了。
回答这题要抓住生命周期和 WAL 可靠性。能说清“快来自少写日志,代价是崩溃恢复和复制语义”,就是合格答案。