71.1. 简介#
BRIN表示块范围索引。BRIN旨在处理某些列与其在表中的物理位置具有一定自然关联的超大型表。
BRIN以块范围(或“页范围”)为单位工作。块范围是表中物理上相邻的一组页;对于每个块范围,索引会存储一些摘要信息。例如,存储商店销售订单的表可能有一个日期列,其中每个订单的日期都记录在该列中,并且大多数情况下,较早订单的条目也会出现在表中较早的位置;存储邮政编码列的表可能将同一城市的邮政编码自然地分组在一起。
BRIN索引可以通过常规位图索引扫描满足查询,如果索引存储的摘要信息与查询条件一致,则将返回每个范围内的所有页中的所有元组。查询执行器负责重新检查这些元组并丢弃与查询条件不匹配的元组 — 换句话说,这些索引是有损的。由于BRIN索引非常小,因此与顺序扫描相比,扫描索引几乎不会增加开销,但可能会避免扫描已知不包含匹配元组的表的大部分。
BRIN索引将存储的具体数据以及索引能够满足的具体查询取决于为索引的每一列选择的运算符类。例如,具有线性排序顺序的数据类型可以具有存储每个块范围内的最小值和最大值的运算符类;几何类型可能会存储块范围中所有对象的边界框。
块范围的大小在索引创建时由pages_per_range
存储参数确定。索引项的数量将等于以页为单位的关系大小除以pages_per_range
的选定值。因此,数字越小,索引就越大(因为需要存储更多索引项),但同时存储的摘要数据可以更精确,并且可以在索引扫描期间跳过更多数据块。
71.1.1. 索引维护#
在创建时,将扫描所有现有的堆页,并为每个范围(包括末尾可能不完整的范围)创建一个摘要索引元组。随着新页被数据填充,已经汇总的页范围将导致摘要信息使用新元组中的数据进行更新。当创建一个不属于最后一个汇总范围的新页时,新页所属的范围不会自动获取摘要元组;这些元组在稍后调用汇总运行之前保持未汇总状态,为该范围创建初始摘要。
有几种方法可以触发页面范围的初始汇总。如果表被清理,无论是手动清理还是通过自动清理,所有现有的未汇总的页面范围都将被汇总。此外,如果启用了索引的自动汇总参数(默认情况下未启用),无论表本身是否由自动清理处理,只要自动清理在该数据库中运行,所有已填充的未汇总页面范围都将进行汇总;见下文。
最后,可以使用以下函数
brin_summarize_new_values(regclass) 汇总所有未汇总的范围; |
brin_summarize_range(regclass, bigint) 仅汇总包含给定页面的范围(如果该范围未汇总)。 |
启用自动汇总时,当检测到下一个块范围的第一页的第一个项目插入时,会向autovacuum
发送请求,以便在下一个自动清理工作程序在同一数据库中完成运行时执行块范围的目标汇总。如果请求队列已满,则不会记录该请求,并且会向服务器日志发送一条消息
LOG: request for BRIN range summarization for index "brin_wi_idx" page 128 was not recorded
发生这种情况时,该范围将保持未汇总状态,直到对表进行下一次常规清理,或者调用上述函数之一。
相反,可以使用brin_desummarize_range(regclass, bigint)
函数对范围进行取消汇总,当索引元组不再是很好的表示形式,因为现有值已更改时,此函数很有用。有关详细信息,请参见第 9.27.8 节。