Postgres选择BTREE而不是BRIN索引

时间:2017-02-07 19:56:05

标签: postgresql indexing postgresql-9.5

我正在运行Postgres 9.5并正在玩BRIN索引。我有一个大约有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索引,对表进行了真空/分析,并重新运行了查询, 选择了BRIN索引,但运行时间相当长:

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

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

由于尺寸较小,我更喜欢使用BRIN索引,但我似乎无法让PG使用它。

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

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

1 个答案:

答案 0 :(得分:9)

似乎BRIN索引扫描不是很有选择性 - 它返回3000万行,所有这些都必须重新检查,这是花费时间的地方。

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

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

因此,表格中的很多块范围在transaction_date_key20170101之间包含20170201,并且必须扫描所有这些块以计算查询结果。

我认为有两种方法可以改善这种情况:

  • 降低pages_per_range存储参数。这将使指数变大,但会减少“误报”数量。

  • 将表格集中在transaction_date_key属性上。如您所知,这需要(至少暂时)列上的B树索引。