【问题标题】:Postgres Temporal / Partitioning Implementation StrategyPostgres 时间/分区实施策略
【发布时间】:2018-02-22 18:01:22
【问题描述】:

我希望在我的应用程序中添加 VALIDTIME 临时支持,并希望获得一些反馈。看起来 Postgres 还没有本地时间支持(我知道有扩展),所以我现在必须采用手动策略。从逻辑上讲,这就是我所追求的:

CREATE TABLE MyPartitionedTable(
    c1 int, 
    ValidTS tstzrange -- VALIDTIME field
)
PARTITION BY LIST (
  (
    CASE WHEN CAST(UPPER(ValidTS) AS DATE) = DATE '9999-12-31' THEN 1 -- Store all current rows in one partition
    ELSE 0 -- Store everything else in another partition
    END
  )
)

时间

当前行UPPER(ValidTS) = '9999-12-31 23:59:59.999999'
旧行UPPER(ValidTS) <> '9999-12-31 23:59:59.999999'

临时删除UPDATE“当前行”和set UPPER(ValidTS) = current_timestamp
临时插入INSERT“当前行”
临时更新:临时DELETE + 临时INSERT(必须在同一事务中完成)

时间选择(当前)SELECT "Current row"
时间选择(AS OF)SELECT ... WHERE ValidTS @> <AS_OF_TS>

分区

Postgres 10 支持本地表分区,所以我想利用它:

  • 当前行的分区(超级快速查找)
  • 历史行的分区(如果需要,可以使用子分区)

我一直在玩它,似乎有一些限制。例如,我不能像上面的例子那样使用CASE 语句——关于IMMUTABLE 表达式的错误。我认为这与使用TIMESTAMP WITH TIME ZONE 有关。此外,文档说您不能在分区表上定义 UNIQUE / PRIMARY KEY 约束。

我的问题

  1. 我的时间设置看起来如何?你的设置是什么?有什么提示或注意事项吗?
  2. 您对时态数据的分区策略是什么?您如何确保快速访问当前行?有什么要注意的吗?

【问题讨论】:

    标签: sql postgresql partitioning ddl temporal


    【解决方案1】:

    您的设置中的一些 cmets:

    1. PostgreSQL 无法自动在分区之间移动行(目前)。
      PostgreSQL 11 中添加了在分区之间自动移动行的支持

    2. 我希望有 validfromvalidto 时间戳,但我只能在您的描述中看到一个时间戳。你想如何实现AS OF

    3. 我认为将时间戳存储为文本不是一个好主意。将其存储为datetimestamptz,则非IMMUTABLE 函数不会有任何问题。然后我会使用infinity 而不是像9999-12-31 这样的任意日期作为活动行。

    我不会对表进行分区,而是使用索引。如有必要,您可以使用... WHERE validto = 'infinity' 创建部分索引。如果当前数据的所有查询都包含相同的条件,则将使用这些索引。我想这取决于您的查询,什么是最好的方法。当然,要加快顺序扫描,只有分区会有所帮助。

    【讨论】:

    • 感谢您的 cmets。几个问题: 1)如果 PG 不自动在分区之间移动行,这是否意味着我需要手动创建触发器以将行插入到审计表中? PG怎么能称之为原生分区呢? 2) ValidTS 是一个tstzrange 数据类型,因此它将validFromvalidTo 存储在同一个字段中,就像PERIOD 数据类型一样
    • 时间戳将存储在tstzrange字段中,没有字符串。不过,我不知道infinity 的值,这就是我需要使用的。感谢您的提示。
    • 这是一个关于在WHERE validTo = 'infinity' 中使用稀疏索引的好技巧。谢谢!我以前没有对 Postgres 进行过性能调优,所以这对我来说是全新的。仅获取当前行数据的查找速度有多快?这与使用非临时表进行相同查找的性能相似吗?
    • 另外(最后一条评论),我读到 PG 10 的表分区实现仍然会创建单独的子表,而不是将所有表数据存储在单个表中。真的吗?这似乎需要很多维护。在 Teradata 中,原生时间支持非常简单。您只需指定一个 VALIDTIME 字段,然后像往常一样执行其他所有操作。它会自动处理所有 DML,所有数据都在同一个表中。看来 PG 还没有完全到位。
    • 关于分区:这是一个新特性,所以还是有一些不足。在UPDATE 上的分区之间移动数据可能会在 v11 中。分区是作为表实现的,但只要这是“幕后”,它就不应该打扰你。 关于时间戳:好的,tstzrange 有意义。 关于索引: 在分区表上通过索引查找与在非分区表上一样快。只有顺序扫描会受到影响,但如果当前值的数量足够小,则对整个部分索引的索引扫描仍然会优于对整个表的顺序扫描。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多