在PostgreSQL中获取表中较大比例的表时,为什么位图扫描比索引扫描更快?

时间:2019-04-12 11:54:19

标签: postgresql indexing postgresql-performance

位图扫描described the difference between Bitmap Heap Scan and Index Scan的作者:

  

一个普通的索引扫描一次从索引中获取一个元组指针,   并立即访问表中的该元组。位图扫描获取   一次性使用索引中的所有元组指针,使用   内存中的“位图”数据结构,然后访问表中的元组   物理元组位置顺序。位图扫描可改善   引用该表的代价是增加了簿记开销   管理“位图”数据结构---并且以数据为代价   不再按索引顺序检索,这与您无关紧要   查询,但是如果您说ORDER BY会很重要。

问题:

  1. 为什么在索引已经排序后又对获取的元组指针进行排序?

  2. 它如何与位图排序?我知道位图是什么,但我不知道如何将其用于排序。

  3. 为什么在获取中等比例的表时比索引扫描更快?相反,它似乎为该过程增加了很多计算。

1 个答案:

答案 0 :(得分:5)

在典型的安装中,Postgres存储的主干由8 KB的数据页组成。每个数据页通常包含许多元组。阅读physical storage in the manual的详细信息。

位图扫描中的“位图”是一种在数据页存储桶中收集元组指针的方法。在此过程中,索引排序顺序必然丢失,有利于物理排序顺序。在“有损模式”下(仅在结果太大或workmem太小以至于即使很小的位图都无法容纳时才会发生),仅保留块号并丢弃相应的元组索引。

此后,仅一次从存储访问每个数据页,以物理顺序提取(可能)多个元组,这对于某些类型的存储也很重要。在有损模式下,必须通过重新检查索引条件来过滤每个已标识页面中的元组。否则,可以使用收集的元组索引直接检索元组。

在索引扫描中,如果多个元组最终存储在同一数据页面中,则可能必须多次访问每个页面。实际过程更加复杂。相关:

对您的问题:

  1. 由于收集匹配并逐页读取数据,因此索引的排序丢失。

  2. 因此,结果必须在附加的排序步骤中再次进行排序-如果需要排序顺序(例如,用ORDER BY进行排序)。

  3. 必须读取的数据页数是整体性能的最主要因素。位图索引扫描将数量减少到最小。有了更快的存储,位图索引扫描的好处就会变小。这就是为什么准确的成本设置对于查询计划者做出良好决策至关重要的原因。