PostgreSQLNotes

第 32 章:面试题精讲

zjc 于 2026-02-01 发布

这是《PostgreSQL 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 本章整理 PostgreSQL 高频面试题,并给出体现工程判断的回答框架。

32.1 MVCC 是什么?

回答要点:

  1. 每行有 xmin / xmax;
  2. 事务根据快照判断可见性;
  3. 读写互不阻塞;
  4. UPDATE 生成新版本;
  5. 旧版本由 VACUUM 清理。

加分项:解释长事务和复制槽如何阻止清理,导致表膨胀。

32.2 VACUUM 的作用?

回收死元组空间、冻结事务 ID、维护可见性映射、支持 Index Only Scan。普通 VACUUM 不归还磁盘空间;VACUUM FULL 会重写表并加重锁。

32.3 为什么索引不生效?

排查顺序:

  1. 索引类型与操作符是否匹配;
  2. 列是否被函数包装;
  3. 类型是否一致;
  4. 是否违背复合索引左前缀;
  5. 统计信息是否过期;
  6. 返回比例是否很高;
  7. 优化器成本判断。

32.4 EXPLAIN ANALYZE 看什么?

看 Seq / Index / Bitmap Scan、rows 与 actual rows、loops、Sort / Hash 内存、Buffers、Rows Removed。不要只看总耗时。

32.5 隔离级别如何选择?

默认 Read Committed 适合多数业务;报表一致性用 Repeatable Read;强一致并发约束用 Serializable,并接受重试成本。

32.6 WAL 的作用?

崩溃恢复、PITR、物理复制、归档。提交策略 synchronous_commit 决定性能与丢数据窗口。

32.7 复制槽为什么危险?

它会保留未被消费的 WAL。下游失效后可能把主库磁盘占满,并引发数据库保护性停止写入。必须监控 restart_lsn 和保留量。

32.8 逻辑复制与物理复制区别?

物理复制传 WAL 数据块变化,一致性强;逻辑复制解析逻辑变更,可按表选择和跨版本,但不复制 DDL、序列状态,且可能有冲突。

32.9 如何处理表膨胀?

先治因:长事务、autovacuum、复制槽、高频无效更新。严重时评估 pg_repack 或窗口内重建,VACUUM FULL 是最后选择。

32.10 B-Tree 和 GIN 如何选择?

B-Tree 适合等值范围排序;GIN 适合 JSONB 包含、数组、全文。GIN 查询强但写入维护成本高。

32.11 JSONB 如何优化?

包含查询建 GIN;高频字段提取生成列;需要范围排序时用表达式或普通列;控制文档大小和更新频率。

32.12 为什么需要连接池?

PostgreSQL 每连接一个进程,过多连接带来内存、调度和锁竞争。连接池复用进程,控制并发,但要理解事务级模式限制。

32.13 分区表注意事项?

分区键要匹配高频过滤;唯一约束包含分区键;提前创建分区;控制分区数量;查询验证分区剪枝。

32.14 如何做性能治理?

用 pg_stat_statements 建立慢 SQL 台账,用 EXPLAIN ANALYZE 定位,用索引和统计优化,用连接池和超时保护,最后压测和固化规范。

32.15 生产高可用方案?

主从复制 + 仲裁 + 自动切换 + 连接路由 + 监控告警 + 演练。明确 RPO/RTO,避免脑裂,旧主恢复前不得继续写。

本章小结

PostgreSQL 面试重点集中在 MVCC、VACUUM、索引、执行计划、WAL、复制、连接池和故障排查。回答时先讲机制,再讲风险和验证方式。

思考题

  1. 如何完整解释一次 UPDATE 的 MVCC 过程?
  2. 表膨胀的治理路径是什么?
  3. 逻辑复制升级要注意什么?
  4. JSONB 查询慢如何系统排查?
  5. 如何设计数据库的 RPO/RTO?