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

net*_*tok 5 postgresql indexing postgresql-performance

位图扫描的作者描述了位图堆扫描和索引扫描之间的区别

一个普通的indexscan一次从索引中获取一个元组指针,然后立即访问表中的该元组。位图扫描一次性从索引中获取所有元组指针,使用内存中的“位图”数据结构对其进行排序,然后以物理元组位置顺序访问表元组。位图扫描提高了表的引用局部性,但要花更多的簿记开销来管理“位图”数据结构---并且不再按索引顺序检索数据,这对您来说无关紧要查询,但是如果您说ORDER BY会很重要。

问题:

  1. 当索引已排序时,为什么又对获取的元组指针进行排序?

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

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

Erw*_*ter 5

在典型安装中,Postgres存储的主干由8 KB的数据页组成。每个数据页通常包含许多元组。阅读手册中有关物理存储的详细信息。

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

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

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

对您的问题:

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

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

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