现在我正在为一个应用程序开发一个数据库模式,该模式需要对几组不同的数值数据进行版本控制,这些数据必须连接在一起才能在视图中使用。该应用程序要求我们能够“回顾”并找到这些多变量在任意时间点的状态。
我使用子查询构建了一些视图定义,以便根据任意连接条件获取各种输入,并根据time_created
字段检查版本。这不是一个严格的SCD2实现,但它很接近。
您可以在此处看到与我们的架构类似的(尽管已大大简化)实现:DB Fiddle link。真正的模式有6个子查询/连接。
这对我的目的非常有效,除了当我们开始将其扩展到数千个“购买”记录时,我们会产生大量的查询成本。对2000多行的查询需要大约1秒,这不适合我们的应用程序。
首先想到的解决方案是创建一个表,该表将“购买”连接到它的各种版本化输入表,在创建购买时由应用程序创建。这应该更有效,但需要更多的模式复杂性。
有人可以就如何最好地规划我的架构/查询向我提供建议,以便最适合这种设置吗?
答案 0 :(得分:2)
我发现这个问题有点令人满意。我觉得忽略这一点有点愚蠢,但你可以把它归结为一个过早优化的案例。代表我。根据维基百科中的学术示例,我在SCD表中省略了end_date
列。我认为这并不是特别必要,因为你需要做的就是倒带'您的表并找到正确的SCD行是找到第一行start_date
小于或等于您在对表进行排序时要查询的日期。但这需要表格排序才能正常运行。
我的查询中的主要瓶颈是通过按时间戳排序中等大(2500+行)的表引起的。我设法通过添加' 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+行表中为字段添加索引,但这似乎对查询时间没有太大影响,但也许我在那里犯了一些错误。无论如何,这似乎更加优化。
可以看到更新的DBFiddle here。
我希望了解如何更好地表达这一点,或者如何更好地说明null
列中的time_ended
值。