必须配合leading使用,单独use_hash不生效;需确保统计信息准确、build表为小表且内存充足,否则可能降级为nested loop或溢出临时表空间。

Oracle 中强制使用 Hash Join 的 Hint 写法是否生效
直接写 /*+ use_hash(a b) */ 不一定生效,必须配合 leading() 明确驱动表顺序,否则优化器可能忽略。常见错误是只加 use_hash 却没指定哪张表先读 —— Hash Join 要求 Build 表(小表)在前,Probe 表(大表)在后,顺序错会导致降级为 Nested Loop 或干脆不生效。
实操建议:
-
leading(a b)必须放在use_hash(a b)前面,表示 a 是 Build 表、b 是 Probe 表 - 若实际数据量与优化器统计偏差大(比如表刚批量插入但未收集统计信息),
use_hash可能被绕过,需先执行DBMS_STATS.GATHER_TABLE_STATS - 多表连接时,
use_hash(b c)仅控制 b 和 c 之间的连接方式,a→b 的连接仍由其他 Hint 或默认策略决定
MySQL 8.0+ 为什么不能用 use_hash hint
MySQL 在 8.0.18 短暂支持过 use_hash 和 no_hash_join,但 8.0.19 起彻底移除 —— 官方认为优化器足够智能,应由成本模型自动选择,而非人工干预。所以你在 MySQL 8.0.25 或更新版本里写 /*+ use_hash(t1 t2) */,会被直接忽略,不会报错也不会生效。
替代方案只有两个:
- 删掉关联字段上的索引,让优化器「被迫」选 Hash Join(因为无索引时 NL 不可行)
- 用
/*+ no_index(t2, idx_col) */隐式禁用索引,效果等同于删索引但更可控 - 确认
optimizer_switch中hash_join=on(默认开启),可通过SELECT @@optimizer_switch验证
Hash Join 内存不足导致 TEMP TABLESPACES 溢出
Oracle 执行 Hash Join 时,Build 表数据全加载进 PGA 内存;若内存不够,会写入临时表空间,出现大量 temp space usage 等待事件,性能断崖下跌。这不是 SQL 写得不好,而是资源配置问题。
关键判断点:
- 执行计划中看到
Operation列含HASH JOIN RIGHT/LEFT (TEMP)或Spill to disk字样 -
A-Rows和E-Rows差距极大,且Used-Mem接近或超过OMem/1Mem - 系统级监控发现临时表空间 I/O 激增
缓解动作优先级:调高 pga_aggregate_target > 改用并行(/*+ parallel(4) */ 分摊内存压力) > 减少 Build 表数据量(加 WHERE 过滤再 Join)
PostgreSQL 的 Hash Join 没走预期路径?检查排序和统计
PostgreSQL 的 Hash Join 触发条件比 Oracle 更严格:不仅要求等值连接,还隐含要求至少一侧无法走 Index Scan(否则倾向用 Nested Loop)。如果你的执行计划里没出现 Hash Join,大概率不是 Hint 问题,而是统计信息不准或查询结构触发了优化器规避逻辑。
排查步骤:
- 运行
EXPLAIN (ANALYZE, BUFFERS),看实际Actual Total Time和Buffers是否异常高 - 执行
VACUUM ANALYZE table_name更新统计,尤其当表有大量 INSERT/DELETE 后 - 避免在 Join 条件字段上用函数(如
UPPER(a.id) = UPPER(b.id)),这会让 Hash Join 失效
PostgreSQL 不支持 use_hash 类 Hint,唯一可控手段是临时关闭某类连接:设置 SET enable_nestloop = off 强制尝试 Hash 或 Merge。










