首页
解决方案
数据库专业技术服务全栈式PostgreSQL解决方案Oracle分布式存储化数据库云PolarDB一体化解决方案
产品
CLup:PostgreSQL高可用集群平台 CMiner: PostgreSQL中的CDC CData高性能数据库云一体机 CBackup数据库备份恢复云平台 CPDA高性能双子星数据库机 CSYun超融合虚拟机产品 ZQPool数据库连接池 ConshGuard数据保护产品 APCC: Greenplum管理平台
文档
文章
客户及伙伴
中启开源
关于我们
公司简介 联系我们
中启开源
登录
×
修改密码

为什么SELECT会产生写?

PostgreSQL 的 SELECT 查询本质上是读操作,但在某些特定场景下,确实会触发写 IO(Write IO)。这通常不是直接写入用户数据,而是数据库为了维护内部状态、保证数据一致性或优化后续性能而进行的后台写入操作。

以下是导致 SELECT 查询产生写 IO 的主要原因:

1. 脏页刷新(Dirty Page Flushing)

这是最常见的原因。

2. 提示位更新(Hint Bits)

这是一个非常典型且容易被忽视的写 IO 来源,特别是在高并发读负载下。

3. 预写日志(WAL)记录

虽然普通的 SELECT 不生成 WAL,但上述的提示位更新在某些配置或特定情况下可能需要记录 WAL(取决于 wal_log_hints 参数及版本行为,通常 Hint Bit 更新不记 WAL 以节省开销,但在某些恢复场景或特定补丁下行为可能不同;不过更主要的是,Hint Bit 导致的脏页最终要落盘)。

4. 临时文件写入(Spill to Disk)

SELECT 查询过于复杂或处理数据量过大,内存不足以支撑操作时,PostgreSQL 会将中间结果写入磁盘上的临时文件。

5. 自动统计信息收集(Autovacuum)

虽然 autovacuum 是后台进程,但它往往由表的读写活动触发。

6. 扩展页面的初始化

总结与排查建议

如果你发现 SELECT 查询期间有明显的写 IO,通常按以下优先级排查:

  1. 检查临时文件使用:查看日志中是否有 “temporary file” 相关记录,或监控 pg_stat_database 中的 temp_filestemp_bytes。如果是排序或哈希溢出,考虑适当调大 work_mem
  2. 观察 Hint Bits 效应:如果是刚大批量导入或更新数据后立即进行全表扫描,极可能是 Hint Bits 更新导致的脏页刷写。随着时间推移,这种现象会减少。
  3. 监控 BgWriter 和 Checkpoint:使用 pg_stat_bgwriter 视图。如果 buffers_checkpointbuffers_clean 很高,说明后台正在努力刷脏页以腾出空间给 SELECT 读取的新页。
  4. 检查 Autovacuum:确认是否有 Vacuum 进程正在运行,清理由读写混合负载产生的死元组。

一句话总结SELECT 产生的写 IO 通常是“为了读而写”(如腾挪缓冲区、更新可见性标记)或“内存不足落盘”(如临时排序),而非直接修改用户业务数据。