Hash Area Size不是调优起点,Oracle 10g后默认自动内存管理,手动设置该参数无效且易导致hash join降级为multipass;应优先确保PGA_AGGREGATE_TARGET充足、构建表真实大小可控,并验证统计信息准确。
Hash Area Size 不是调优的起点,而是最后才碰的参数。Oracle 10g 之后默认启用自动内存管理(WORKAREA_SIZE_POLICY=AUTO),硬调 HASH_AREA_SIZE 不仅无效,还可能干扰 PGA 自动分配,导致 hash join 降级为多遍(multipass)甚至频繁写临时段。
在 Oracle 9i 及更早版本中,HASH_AREA_SIZE 是控制 hash join 内存用量的直接参数;但从 10g 开始,它被标记为 deprecated,仅在 WORKAREA_SIZE_POLICY=MANUAL 时生效。而当前绝大多数生产库都用 AUTO 模式,此时设置 HASH_AREA_SIZE 完全被忽略——你看到的执行计划里仍出现 “HASH JOIN” 并不意味着它真用了你设的值。
HASH_AREA_SIZE 的值只影响单个会话的 hash 工作区上限,但不保证实际分配到这么多PGA_AGGREGATE_TARGET 过小,即使 HASH_AREA_SIZE 设得再大,也会被截断判断 hash join 是否能走最优路径(optimal),关键不是 HASH_AREA_SIZE,而是看构建表能否完整装入内存。这取决于:
PGA_AGGREGATE_TARGET:必须足够大,建议设为物理内存的 20%–30%(OLTP)或 40%–50%(DSS/报表)_hash_multiblock_io_count:影响 hash 构建阶段的 I/O 效率,默认值 9 偏低,可尝试设为 16 或 32(需测试)DBA_TABLES.BLOCKS × DB_BLOCK_SIZE):如果 > PGA_AGGREGATE_TARGET × 0.2,大概率触发 multipass例如:构建表占用 800MB,PGA_AGGREGATE_TARGET=2G,理论上仍有空间;但如果并发查询多,实际可用 PGA 可能只剩 300MB,就会 fallback 到磁盘。
运行 SQL 后查 V$SQL_WORKAREA_ACTIVE 或用 10046 trace,重点关注这几项:
OPTIMAL_EXECUTIONS = 0:说明没走最优路径ONEPASS_EXECUTIONS > 0:表示一遍 hash,尚可接受MULTIPASS_EXECUTIONS > 0:已写临时段,I/O 暴增,性能雪崩TEMPSEG_SIZE > 0:明确写了临时表空间,立刻排查构建表大小和 PGA注意:V$SQL_PLAN_STATISTICS_ALL 中的 IO_COST 突增、BYTES 显著高于预估,也是 multipass 的典型信号。
与其纠结 HASH_AREA_SIZE,不如做这些见效更快的操作:
USE_HASH(t1 t2) 提示强制指定,但前提是 t1 行数少且连接列选择性高NUM_ROWS 和 AVG_ROW_LEN 会让优化器误判构建表大小,用 DBMS_STATS.GATHER_TABLE_STATS 重收集真正卡住性能的,往往不是内存参数设得不够高,而是构建表选错了、统计信息不准、或者根本没意识到那个“小表”其实有 500 万行稀疏数据——这时候调任何 HASH_AREA_SIZE 都没用。