- BitmapIndex Scan 与BitmapHeap Scan
BitmapIndex Scan 与Index Scan 很相似,都是基于索引的扫描,但是BitmapIndex Scan 节点每次执行返回的是一个位图而不是一个元组,其中位图中每位代表了一个扫描到的数据块。而BitmapHeap Scan一般会作为BitmapIndex Scan 的父节点,将BitmapIndex Scan 返回的位图转换为对应的元组。这样做最大的好处就是把Index Scan 的随机读转换成了按照数据块的物理顺序读取,在数据量比较大的时候,这会大大提升扫描的性能。
我们可以运行set enable_indexscan =off; 来指定关闭Index Scan ,上文中Index Scan 中SQL 的EXPLAIN 输出结果则变为:
postgres=> explain(ANALYZE,VERBOSE,BUFFERS) select * from class where st_no=2;QUERY PLAN
-----------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on public.class (cost=4.29..8.30 rows=1 width=35) (actual time=0.025..0.025 rows=1 loops=1)Output: st_no, nameRecheck Cond: (class.st_no = 2)Heap Blocks: exact=1Buffers: shared hit=3-> Bitmap Index Scan on no_index (cost=0.00..4.29 rows=1 width=0) (actual time=0.019..0.019 rows=1 loops=1)Index Cond: (class.st_no = 2)Buffers: shared hit=2Planning time: 0.088 msExecution time: 0.063 ms
(10 rows)
这是一个针对名为"class"的表执行的查询计划解释,查询目标是选择"st_no"等于2的行。下面是对每个步骤的详细解释:
- Bitmap Heap Scan on public.class:
这是一个使用位图堆扫描的操作,意味着数据库系统将使用位图索引来找到符合条件的行。它会扫描名为"class"的表。 预计执行成本(cost)在4.29到8.30之间,这是一个估计值。 预计返回1行,宽度为35个单位。 实际执行时间为0.025毫秒,只有1行符合条件。 执行次数为1。
- Recheck Cond: (class.st_no = 2):
在这个步骤中,系统会重新检查前一个条件,确保返回的行确实满足查询条件。 检查的条件是"class.st_no = 2",即"st_no"等于2。 堆块(Heap Blocks):这里使用了一个堆块,这是一个精确的值,表示内存中的块数。 缓冲区(Buffer):在这个步骤中,共使用了3个共享缓冲区,其中1个被精确地命中。
- Bitmap Index Scan on no_index:
这是一个使用位图索引扫描的操作,系统会使用名为"no_index"的索引。 预计执行成本为0.00到4.29之间。 预计返回1行,宽度为0,因为这是一个索引扫描,不返回实际的列数据。 实际执行时间为0.019毫秒,只有1行符合条件。 执行次数为1。 索引条件是"(class.st_no = 2)",表示"st_no"等于2。
- Planning time:
优化器花费的规划时间,为0.088毫秒。
- Execution time
:整个查询的执行时间,为0.063毫秒。 总结:该查询使用了位图索引扫描和位图堆扫描,通过索引快速定位到符合条件的行,然后进一步确认行是否真正符合条件。整个查询的执行时间非常短,性能较高。