在 Postgres 中优化 SCD2 JOINS

Optimizing SCD2 JOINS in Postgres

现在我正在为一个应用程序开发数据库模式,该应用程序需要对几组不同的数字数据进行版本控制,这些数据必须连接在一起才能在视图中使用。该应用程序要求我们能够 'look back' 并找到这些多个变量在任意时间点的状态。

我已经建立了一些视图定义,使用子查询根据任意连接条件获取各种输入,并根据 time_created 字段检查版本。这不是严格的 SCD2 实现,但很接近。

您可以在此处看到与我们的架构类似(尽管大大简化)的实现:DB Fiddle link。真实模式有 6 subqueries/joins.

这对我的目的来说非常有效,除了当我们开始将其扩展到数千条 'purchase' 记录时,我们会产生大量查询成本。针对 2000 多行的查询耗时约 1 秒,这对我们的应用程序来说是不合适的table。

我想到的第一个解决方案是创建一个 table,它将 'purchase' 连接到它的各种版本输入 table,由应用程序在购买时创建创建。这应该更有效,但需要更多的模式复杂性。

任何人都可以就如何最好地规划我的 schema/queries 以最适合这种设置提供建议吗?

我找到了一个比较满意的解决这个问题的办法。我觉得忽略这一点有点愚蠢,但你可以代表我把它归结为 'premature optimization' 的情况。根据维基百科中的学术示例,我在我的 SCD table 中省略了 end_date 列。我认为这不是特别必要,因为您需要做的就是 'rewind' 您的 table 并找到正确的 SCD 行是找到 start_date 小于或等于日期的第一行您正在查询 table 的排序时间。但这需要 table 排序才能正常运行。

我的查询中的主要瓶颈是由按时间戳对中等大小(2500 多行)table 进行排序造成的。我设法通过添加 'end_date' 列并更改要使用的查询(简化示例)来解决此问题:

LEFT JOIN LATERAL ( SELECT * FROM tax t
  WHERE p.time_created >= t.time_created AND p.time_created <= COALESCE(t.time_ended, '9999-12-30'::date)) current_tax ON true
....

这将查询从 ~1 秒减少到 <100 毫秒。我尝试为 2500+ 行 table 中的字段添加索引,但这似乎对查询时间没有太大影响,但也许我在那里犯了一些错误。无论如何,这似乎更优化了。

可以看到更新的 DBFiddle here

关于如何更好地表示这一点,或者如何更好地解释 time_ended 列中的 null 值,我希望得到一些建议。