为什么PostgreSQL中的Hash Join在内存不足时会严重变慢?

秋磊小哥_6728

秋磊小哥_6728

2026-06-07

458人浏览

原创

Hash Join落盘主因是work_mem不足致哈希表整桶刷磁盘,引发IO爆炸;需先通过EXPLAIN(ANALYZE,BUFFERS)确认Disk Usage非零、排除数据倾斜与统计信息过期,再按操作节点独享原则设32MB~64MB并用SET LOCAL临时调整。

为什么postgresql中的hash join在内存不足时会严重变慢?

Hash Join落盘不是“慢一点”,是IO爆炸

Hash Join在work_mem不足时写磁盘,性能断崖式下跌——不是算法本身变慢,而是从内存随机访问退化成磁盘随机读写。一次哈希探查(probe)本该是纳秒级指针跳转,变成毫秒级磁盘寻道,放大10⁵倍以上。

典型症状包括:EXPLAIN (ANALYZE, BUFFERS)中出现大量Temp Read/Temp Write块、Execution Time里IO耗时占比超70%、Shared Hit骤降而Local Hit暴增。

  • PostgreSQL不会只写“一部分”哈希表:它按桶(bucket)切片,一旦内存不够,就整批刷到临时文件,后续每次probe都要反复读磁盘
  • 临时文件默认放在pg_temp_*目录,不走shared_buffers缓存,OS page cache也难命中(因访问模式高度随机)
  • 日志里若出现writing to disk due to insufficient memory,就是明确信号,不用再猜

怎么确认真是work_mem不够,而不是其他问题?

别一看到Hash Join就调work_mem——数据倾斜、统计信息过期、类型不一致这三类问题更隐蔽,且调内存完全无效。

九歌
九歌

一款专注于中文诗歌创作的人工智能写作系统,可围绕主题和表达需求辅助生成具有诗歌形式的中文文本。

下载
  • 先跑EXPLAIN (ANALYZE, BUFFERS),检查Hash节点的Disk Usage是否非零;如果为0,说明根本没落盘,work_mem不是瓶颈
  • 查pg_stat_progress_hash(v12+),看hash_probe_total_buckets / hash_buckets_used比值:若远大于3,说明哈希桶严重稀疏,是work_mem太小被迫建了过多低效桶
  • 快速验数据倾斜:SELECT key, COUNT(*) FROM table GROUP BY key ORDER BY 2 DESC LIMIT 5;若TOP1频次 > 平均值×10,加内存基本白费
  • 检查JOIN字段类型:比如CAST(u.id AS TEXT) = o.user_id会导致索引失效+类型强制转换,优化器只能硬Hash,且无法缩小驱动表规模

work_mem设多大才真有用?

work_mem是“每个操作节点”独享的上限,不是整个查询或会话的总和。一个含2个Hash Join + 1个Sort的查询,可能同时吃掉3×work_mem。

  • 估算下限:对驱动表Join键粗略计算——(行数 × (键长度 + 8)) × 1.5(1.5是哈希填充因子预留)
  • 中小负载建议从'32MB'起步,高分析负载可试'64MB';超过'128MB'需严格评估并发压力
  • 临时调优务必用SET LOCAL work_mem = '64MB',仅对当前事务生效;全局改work_mem极易引发OOM
  • 注意连接池干扰:pgbouncer默认拦截SET命令,需确认其ignore_startup_parameters未屏蔽work_mem

为什么调了work_mem还是写磁盘?

数值看着够,但实际仍落盘,问题常出在并发、并行或操作叠加的细节里。

  • 开了并行查询(max_parallel_workers_per_gather = 4),每个worker都独立申请work_mem,但pg_stat_progress_hash只反映主进程状态,容易误判
  • 同一查询含Hash Join + Sort + DISTINCT,三者各自吃一份work_mem,总开销是三倍,你只给了单个额度
  • 单位写错:写成'64M'(缺B)会被静默转成64字节;写成67108864虽对,但易手误少零
  • shared_buffers和effective_cache_size再大也没用——它们不参与哈希表构建,调了纯属浪费

真正卡住的点往往不在work_mem本身,而在你没意识到:一个查询里可能有多个独立内存消费者,而你只盯着Hash节点看。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
postgresql常用命令
postgresql常用命令

postgresql常用命令psql、createdb、dropdb、createuser、dropuser、\l、\c、\dt、\d table_name、\du、\i file_name、\e和\q等。本专题为大家提供postgresql相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.10

233

5

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4869

19

postgresql常用命令有哪些
postgresql常用命令有哪些

postgresql常用命令psql、createdb、dropdb、createuser、dropuser、\l、\c、\dt、\d table_name、\du、\i file_name、\e和\q等。更详细的postgresql常用命令,大家可以访问下面的文章。

2023.11.16

647

3

postgresql常用命令介绍
postgresql常用命令介绍

postgresql常用命令有\l、\d、\d5、\di、\ds、\dv、\df、\dn、\db、\dg、\dp、\c、\pset、show search_path、ALTER TABLE、INSERT INTO、UPDATE、DELETE FROM、SELECT等。想了解更多postgresql的相关内容,可以阅读本专题下面的文章。

2023.11.20

1396

6

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

2026.02.12

500

19

PostgreSQL 性能优化与查询执行计划实战
PostgreSQL 性能优化与查询执行计划实战

本专题深入解析PostgreSQL性能优化核心,聚焦查询执行计划的实战应用。通过EXPLAIN命令精准定位瓶颈,结合索引策略、SQL改写与参数调优,系统提升查询效率。从执行计划解读到性能调优全流程,助你掌握数据库性能诊断与优化实战能力。

2026.05.08

170

10

PostgreSQL 在 Next.js / Go 全栈架构中的工程化实践
PostgreSQL 在 Next.js / Go 全栈架构中的工程化实践

本文详解如何利用Next.js(搭配Drizzle ORM)与Go后端构建高性能应用,充分发挥PG在JSONB非结构化存储与pgvector向量检索上的优势。从数据建模到Docker容器化部署,打造支持AI时代的“One Database”工程化解决方案。

2026.05.08

901

10

PostgreSQL高级特性、内核机制与现代数据架构
PostgreSQL高级特性、内核机制与现代数据架构

本专题从MVCC并发控制与WAL日志等内核机制出发,详解JSONB、PostGIS及pgvector等高级特性。探讨如何利用单一引擎支撑关系型、向量及图数据等现代数据架构需求,助您掌握构建高并发、智能化应用的核心技术。

2026.05.08

244

10

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

2023.06.29

3085

3

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Swoft2.x速学之http api篇课程
Swoft2.x速学之http api篇课程

共16课时 | 1.5万人学习

php初学者入门课程
php初学者入门课程

共10课时 | 1万人学习

PHP基础入门课程
PHP基础入门课程

共33课时 | 3.5万人学习