处理 PARTITION BY RANGE 上超出范围的值

Not*_*hor 3 postgresql partitioning plpgsql postgresql-10

我有一个用于存储事件的表,该表timestamptz使用按月按列分区PARTITION BY RANGE

目前有 5 个分区,每个分区包含一个月的跨度,从 开始FOR VALUES FROM ('2018-01-01') TO ('2018-02-01')到结束FOR VALUES FROM ('2018-05-01') TO ('2018-06-01')

大多数数据都是以线性且可预测的方式输入的。但是,事件由报告事件的应用程序消耗,并且我确实必须允许随时输入过去的事件 - 其时间戳可能早于2018-01-01,甚至是未来的事件(例如预计的费用)发生在未来的某个时间)。

我计划为过去的事件创建一个分区,这些事件的跨度将超过一个月,因为预计不会有太多此类事件。

我不确定对于尚未存在分区的未来事件的最佳方法是什么。

有没有办法获取我可以在现有分区中存储的最小/最大值?如果没有,我可以创建一个参考表来存储这些值,但我宁愿不必维护它。

我应该创建一个触发器来检查插入的每一行(看起来很昂贵)吗?我应该捕获插入错误并一次处理这些错误吗?

运行于PostgreSQL 10.3.

Erw*_*ter 5

有没有办法获取我可以在现有分区中存储的最小/最大值?

你还在评论中问:

您知道如何通过查询获取范围的下限和上限吗?

我不知道有任何专门用于此特定目的的系统目录信息功能。但:

我们可以根据这组线索构建一个查询。基于手册中范围分区的示例

SELECT i.inhrelid::regclass
     , partition_bound
     , split_part(partition_bound, '''', 2) AS lower_bound
     , split_part(partition_bound, '''', 4) AS upper_bound
FROM   pg_inherits i
JOIN   pg_class    c ON c.oid = i.inhrelid
     , pg_get_expr(c.relpartbound, i.inhrelid) AS partition_bound
WHERE  inhparent = 'measurement'::regclass;
Run Code Online (Sandbox Code Playgroud)
因赫雷利德 | 分区绑定 | 下限 | 上限
:-------------------- | :------------------------------------------------------------ | :---------- | :----------
测量_y2006m02 | 对于从 ('2006-02-01') 到 ('2006-03-01') 的值 | 2006-02-01 | 2006-03-01
测量_y2006m03 | 对于从 ('2006-03-01') 到 ('2006-04-01') 的值 | 2006-03-01 | 2006-04-01

db<>在这里摆弄

限制:

  • 基于单引号从字符串中提取下限和上限是廉价且肮脏的。可能有一种更干净的方法可以直接从中提取价值relpartbound
  • 只包括第一层传承。您必须递归地遍历图表pg_inherits才能覆盖子分区。
  • 这建立在声明性分区的几个实现细节之上,这是 Postgres 10 的一项新功能。虽然我不认为查询会因为下一个主要版本之一的更改而中断,但有可能会中断。

  • 谢谢!我在它周围添加了一个 CTE,并采用了“min(lower_bound)”和“max(upper_bound)”。我同意你关于“便宜又脏”的评论,但它现在可以满足我的需要。 (2认同)