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 中的很多块范围包含 20170101
和 20170201
之间的 transaction_date_key
,并且必须扫描所有这些块以计算查询结果。
我看到两个改善情况的选项:
降低pages_per_range
存储参数。这将使索引更大,但会减少“误报”块的数量。
在 transaction_date_key
属性上群集 table。正如您所发现的,这需要(至少暂时)列上的 B-tree 索引。
我运行正在使用 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 中的很多块范围包含 20170101
和 20170201
之间的 transaction_date_key
,并且必须扫描所有这些块以计算查询结果。
我看到两个改善情况的选项:
降低
pages_per_range
存储参数。这将使索引更大,但会减少“误报”块的数量。在
transaction_date_key
属性上群集 table。正如您所发现的,这需要(至少暂时)列上的 B-tree 索引。