Postgres 选择 BTREE 而不是 BRIN 索引

Postgres choosing BTREE instead of BRIN index

我运行正在使用 Postgres 9.5,正在研究 BRIN 索引。我有一个事实 table 大约有 1.5 亿行,我正试图让 PG 使用 BRIN 索引。我的查询是:

select sum(transaction_amt), 
       sum (total_amt) 
from fact_transaction 
where transaction_date_key between 20170101 and 20170201 

我在列 transaction_date_key 上同时创建了 BTREE 索引和 BRIN 索引(默认 pages_per_range 值为 128)(上述查询指的是 2017 年 1 月至 2 月)。我原以为 PG 会选择使用 BRIN 索引,但它与 BTREE 索引一起使用。这是解释计划:

https://explain.depesz.com/s/uPI

然后我删除了 BTREE 索引,对 table 进行了清理/分析,然后重新运行 查询并做了 选择BRIN 索引但是 运行 时间相当长:

https://explain.depesz.com/s/5VXi

事实上,当使用 BTREE 索引而不是 BRIN 索引时,我的测试都更快。我以为应该是相反的?

我更喜欢使用 BRIN 索引,因为它的大小较小,但我似乎无法让 PG 使用它。

注意:我加载了从 2017 年 1 月到 2017 年 6 月(通过 transaction_date_key 定义)的数据,因为我读到物理 table 排序在使用 BRIN 索引时会有所不同。

有谁知道为什么 PG 选择使用 BTREE 索引以及为什么 BRIN 在我的情况下这么慢?

看来BRIN索引扫描的选择性不是很强——returns3000万行,全部都得re-checked,时间就花在了这里。

这可能意味着 transaction_date_key 与 table 中行的物理位置没有很好的相关性。

A BRIN index works 通过将 table 块的范围“集中在一起”(多少可以使用存储参数 pages_per_range 配置,其默认值为 128)。存储块的 eatch 范围的索引值的最大值和最小值。

所以你的 table 中的很多块范围包含 2017010120170201 之间的 transaction_date_key,并且必须扫描所有这些块以计算查询结果。

我看到两个改善情况的选项:

  • 降低pages_per_range存储参数。这将使索引更大,但会减少“误报”块的数量。

  • transaction_date_key 属性上群集 table。正如您所发现的,这需要(至少暂时)列上的 B-tree 索引。