postgresql中位图扫描不是join算法,而是单表扫描方式,仅在某张表的where过滤阶段启用,取决于其索引、统计信息和条件选择性;它与nested loop、hash join等连接算法正交独立。

Bitmap Index Scan)根本不是 JOIN 算法,而是**单表扫描方式之一**。它只发生在 JOIN 的某一张参与表(通常是内表或驱动表)的 WHERE 条件过滤阶段,和 JOIN 本身无关。
真正决定 JOIN 行为的是连接算法(Nested Loop、Hash Join、Merge Join),而是否对某张表启用 Bitmap Index Scan,取决于这张表自身的过滤条件、索引结构和统计信息。
什么时候会在 JOIN 中看到 Bitmap Index Scan?
它只出现在 JOIN 执行计划的某一张表的扫描节点里,常见于以下情况:
- 该表的 JOIN 条件 + 其他 WHERE 条件能同时命中多个独立索引(例如
ON t1.id = t2.t1_id WHERE t2.status = 'active' AND t2.created_at > '2025-01-01',且status和created_at各有单列索引) - 查询返回行数中等(比如几千到几十万),既不够少到走
Index Scan回表最优,也不够多到直接Seq Scan更省事 -
work_mem足够大,能容纳位图内存结构(默认 4MB,太小会导致降级为Index Scan或退化为顺序扫描) - 优化器估算出位图扫描的总代价(索引扫描 + 位图构建 + 堆扫描)低于其他路径
Bitmap Index Scan 和 JOIN 算法是正交的
你完全可能看到这样的组合:
-
Hash Join内部,右表用Bitmap Heap Scan(即位图扫描回表)加载数据 → 常见于大表 JOIN 小表,且右表有复合过滤条件 -
Nested Loop中,内表每次被驱动时走Index Scan,但若内表加了额外 WHERE 条件,也可能触发Bitmap Index Scan(不过更少见,因为 NLJ 通常期望快速单点定位) -
Merge Join要求两边有序,通常依赖Index Scan或Sort,基本不会用位图扫描(位图不保序)
换句话说:Bitmap Index Scan 是“怎么从一张表里捞数据”,Hash Join 是“两张表怎么配对”,二者属于不同层级的决策。
为什么容易误以为它“优先”?
实际观察中,你常在 EXPLAIN ANALYZE 输出里看到类似结构:
PostgreSQL 18.4 官方 Ubuntu 安装包现已发布,这是目前最新的稳定版本。推荐通过官方 APT 仓库安装:先执行 sudo apt update 更新索引,再运行 sudo apt install postgresql-18 即可完成部署。新版本引入了异步 I/O 子系统,在顺序扫描与 VACUUM 场景下性能提升显著,同时支持 UUID v7 原生生成函数与虚拟生成列。
Hash Join (cost=123.45..678.90 rows=5000 width=128)
Hash Cond: (t2.t1_id = t1.id)
-> Bitmap Heap Scan on t2 (cost=10.20..520.30 rows=5000 width=64)
Recheck Cond: (status = 'active'::text)
-> Bitmap Index Scan on idx_t2_status (cost=0.00..10.00 rows=5000 width=0)
Index Cond: (status = 'active'::text)
-> Seq Scan on t1 (cost=0.00..100.00 rows=10000 width=64)
这里 t2 的扫描用了位图,只是因为它自身过滤条件适合,并非 JOIN 策略偏好它。如果把 t2.status = 'active' 换成 t2.id = 123(主键等值),优化器大概率改用 Index Scan;如果去掉所有 WHERE,就变成 Seq Scan。
调优时真正该盯住的点
别盯着“为什么用了位图”,而要看:
- 位图扫描的
rows估算是否严重偏离实际(EXPLAIN ANALYZE中看 actual rows vs planned rows),偏差大会误导 JOIN 顺序选择 -
Bitmap Heap Scan后面有没有大量Recheck Cond—— 这说明位图精度不足,需二次过滤,IO 和 CPU 开销都会上升 - 是否因缺少复合索引,被迫用多个单列索引拼出位图?比如
WHERE a = ? AND b > ?,建INDEX ON t(a, b)往往比依赖位图更高效 -
work_mem是否被多个并发查询挤占,导致本该用位图的场景被迫降级
位图扫描本身是优化器在特定数据分布下的务实妥协,不是银弹。它的存在感强,是因为它常出现在“难搞”的中等规模过滤场景里——而这恰恰是业务 SQL 最常卡住的地方。










