三种连接节点的选择依据
计划树里连接以三种形态出现:嵌套循环、哈希连接、归并连接。选择依据是驱动侧估算行数、内表连接列是否有索引、两侧数据是否已经有序。看计划时先判断节点类型,再判断它是否与实际数据规模相匹配:驱动侧只有几十行却选了哈希连接,或者驱动侧几万行却选了嵌套循环,都是明显的信号。
基本信息
| 适用平台 | PostgreSQL 12 及以上 |
|---|---|
| 嵌套循环 | 驱动集小、内表连接列有索引时逐行查找 |
| 哈希连接 | 等值连接且两侧数据量较大,构建哈希表后探测 |
| 归并连接 | 两侧已按键有序(排序结果或索引输出) |
| 并行执行 | 计划里出现收集节点表示使用了并行工作进程 |
典型使用场景
- 大表等值连接变慢:确认哈希连接是否因内存不足而分批落盘
- 小结果集连接:确认走的是嵌套循环而不是笨重的哈希构建
- 两表都很大且已排序:归并连接可能是最优选择
- 评估并行度:看收集节点与计划工作进程数是否符合预期
- 对比调整内存参数前后的节点变化
识别连接节点
识别连接节点
EXPLAIN
SELECT u.name, o.total
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE u.city = 'shanghai';
-- 输出里可能出现哈希连接节点:
-- Hash Join (cost=...)
-- Hash Cond: (o.user_id = u.id)
-- 嵌套循环:常见于驱动侧很小、内表连接列有索引的情况
-- 归并连接:两侧按键有序时出现
-- 需要真实行数与内存使用时用分析模式(会真实执行)
-- EXPLAIN (ANALYZE, BUFFERS) SELECT ... ;
-- 哈希表超出内存会分批落盘,输出中会给出批次与磁盘占用信息
-- 先按会话调整排序与哈希内存上限,验证后再决定是否落到实例配置连接节点选择依据
| 节点类型 | 适用场景 | 异常信号 |
|---|---|---|
| 嵌套循环 | 驱动集小、内表连接列有索引 | 驱动集很大且内表无索引 |
| 哈希连接 | 等值连接、两侧数据量较大 | 哈希批次很多、磁盘占用大 |
| 归并连接 | 两侧已按键有序 | 为它额外排序付出高代价 |
| 并行收集节点 | 大表扫描与聚合 | 工作进程数远超预期占用资源 |
| 物化节点 | 中间结果需要重用 | 物化行数远超估算 |
哈希连接本身没有好坏之分:它在数据量大时通常是对的选择,真正的问题往往是内存上限偏小,导致哈希表分批落盘。先看输出里的批次与磁盘占用,再决定是否调内存。
并行执行会放大资源占用:并发请求多时,每条语句的并行工作进程叠加起来可能吃满 CPU。评估并行度要看实例的整体并发,不只盯单条语句的耗时。