Postgres 中 BRIN 索引的测试效率

vvo*_*dra 6 postgresql index-tuning

我在 BRIN 索引的 OLAP 查询中发现了许多用例,因为它们要小得多,并且速度与 BTREE 索引处于同一数量级。

通常,我使用 BRIN 索引来单调(或接近)增加时间戳列。在我们的 OLTP 数据库中,它们紧密地放置在磁盘上,因为随着时间的推移,它们自然会按顺序写入。

在我们的仓储 Postgres 实例中,表的某些部分是大批量加载的,不一定按时间排序。

是否有一些分析查询可以告诉我数据是否放置得太随机而无法使用 BRIN,即使列值分布似乎应该遵循创建 BRIN 索引的所有先决条件?

Erw*_*ter 5

BRIN 索引仅对大表(数千个数据页或更多)有意义。(您已经知道这一点,只是为了指导公众。)但是如何判断行是否进行了足够的物理排序呢?

手册给出了一个提示:

BRIN 索引(块范围索引的简写)存储有关存储在表的连续物理块范围中的值的摘要。因此,它们对于值与表行的物理顺序密切相关的列最有效 。

大胆强调我的。

ANALYZE收集存储在 中的相应统计数据pg_statistic。人类最好通过correlation系统视图中的列进行访问:pg_stats

correlation float4

物理行排序和列值的逻辑排序之间的统计相关性。范围从 -1 到 +1。当该值接近 -1 或 +1 时,由于减少了对磁盘的随机访问,因此该列上的索引扫描预计会比该值接近零时更便宜。(如果列数据类型没有运算符,则该列为空<。)

所有统计数据均基于行样本,因此即使是最新的,也只是估计值。ANALYZE您可以通过增加样本量来提高有效性,即设置更高的“统计目标”——当然,这也会增加成本。默认default_statistics_target值为 100,这对于大多数用途来说都可以,但对于具有非平凡数据分布(用于排序和过滤)的大表的列来说通常太低。看:

您甚至可以暂时增加统计目标,运行ANALYZE并重置该值,以获得具有更高有效性的一次性相关性。

因此,一旦分析了表(手动或通过autovacuum)检查:

SELECT schemaname, tablename, attname, n_distinct, correlation
FROM   pg_stats
WHERE  schemaname = 'public'
AND    tablename  = 'tbl'
AND    attname    = 'my_index_col';
Run Code Online (Sandbox Code Playgroud)
  • 接近correlation0意味着 BRIN 指数将毫无用处

  • 接近correlation1 -1)意味着 BRIN 指数非常好。

    • 如果计数较低n_distinct(相对于总计数)或负比率接近 0,您可以pages_per_range相应地增加设置(默认为 128)。
    • 如果计数较高n_distinct(相对于总计数)或接近 -1 的负比率,您可以pages_per_range相应地减少设置。
  • 介于两者之间的一切都是灰色地带。许多因素在起作用。还很大程度上取决于平均行大小和典型查询。根据我的经验,接近 0 或 1 / -1 的值很常见,这使得决策变得很容易。

也就是说,如果表排序不够,您可以使用阻塞性较小的社区工具pg_squeezepg_repack之一来进行排序。对于大表来说,按排序顺序重写整个表的成本很高,并且如果存在(或+ ) 操作,情况会随着时间的推移而恶化。但可以为某些用例付费。看:CLUSTERUPDATEDELETEINSERT

  • 请注意,即使有一个异常值也会破坏块范围的最小值或最大值。因此,鉴于这些是统计数据,我不确定 1 的“相关性”是否足够好。 (2认同)