【问题标题】:Postgres choosing BTREE instead of BRIN indexPostgres 选择 BTREE 而不是 BRIN 索引
【发布时间】:2017-06-25 05:25:03
【问题描述】:

我正在运行 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 月到 2017 年 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 在我的情况下要慢得多?

【问题讨论】:

  • 你能告诉我们explain (analyze, verbose, buffers, timing)的输出而不是“just”explain (analyze)
  • 当然 - 现在运行它们。
  • B-Tree 和 BRIN:explain.depesz.com/s/S3Zp 仅限 BRIN:explain.depesz.com/s/Z1A5
  • 我自己没有使用过 BRIN 索引,但我的理解是,只有当您的数据以与您的查询和 BRIN 索引匹配的方式在磁盘上排序时,它们才能正常工作。您是否尝试在您的表上运行 CLUSTER?
  • 对不起,不去那里。我试图对表进行聚类,但是使用 BRIN 类型索引似乎无法进行聚类。我输入了CLUSTER fact_transaction USING i_fact_transaction_transaction_date_key;,但它返回ERROR: cannot cluster on index "i_fact_transaction_transaction_date_key" because access method does not support clustering SQL state: 0A000

标签: postgresql indexing postgresql-9.5


【解决方案1】:

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

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

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

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

我看到了两种改善情况的选择:

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

  • transaction_date_key 属性上对表进行聚类。正如您所发现的,这需要(至少暂时)列上的 B 树索引。

【讨论】:

    猜你喜欢
    • 2011-03-18
    • 2016-01-05
    • 2021-07-21
    • 2020-07-06
    • 1970-01-01
    • 2018-05-10
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    相关资源
    最近更新 更多