Hasura 计算字段 vs. Postgres 生成列 vs. Postgres 视图

4

我们正在实施一个电子商务数据模型,但在Postgres生成的列、Hasura计算字段和Postgres视图之间犹豫不决。

简化而言,我们有两张表:

items
------------
id
order_id
unit_price
quantity

orders
------------
id

我们现在希望在items表中添加total_price(即unit_price * quantity),并且在订单中添加total_price(即该订单中所有itemstotal_price之和)。
在第一个情况下,我们使用了Postgres生成的列。这里的好处似乎是它只需要生成一次并存储起来,而不像Hasura计算字段那样在每次查询时都要重新运行。
这是正确的选择吗?
items
------------
id
order_id
unit_price
quantity
total_price : Postgres generated column : (unit_price * quantity)

CREATE TABLE orders (
    ...,
    total_price integer GENERATED ALWAYS AS (unit_price * quantity) STORED
);

在第二种情况下,我们无法使用生成的列,因为它不能引用不同表中的字段。相反,我们可以使用Hasura计算字段来解决这个问题。
orders
------------
id
total_price : Hasura computed field : SUM(items.total_price)

CREATE FUNCTION calculate_order_total_price(orders_row orders)
RETURNS INTEGER AS $$
    SELECT CAST(SUM(total_price) AS INTEGER)
      FROM items
     WHERE order_id = orders_row.id
$$ LANGUAGE sql STABLE;

或者,我们可以创建一个Postgres视图:

vw_orders
------------
orders.id
total_price : SELECT SUM(items.total_price)

CREATE VIEW vw_orders AS 
    SELECT orders.id,
        (SELECT sum(items.total_price) AS sum
           FROM items
          WHERE (items.order_id = orders.id)) AS total_price
        FROM orders;

Hasura计算字段的解决方案的缺点是只在GraphQL查询中公开了total_price,因此我们无法在SQL中使用它。

Postgres视图解决方案乍一看似乎没有任何问题。

我们有什么遗漏吗?

为什么会有人使用Hasura计算字段而不是Postgres生成的字段或视图呢?

是否有比较表或流程图可以帮助我们决定在每种特定情况下哪种方法最好?

最后,对于所有这些,我们当然也可以使用Postgres触发器、Hasura事件触发器和Hasura操作……那么什么时候使用这些才是适当的解决方案?

干杯!

1个回答

2
针对这种情况,我建议选择使用PostgreSQL视图,因为涉及的计算较为简单(只有一个乘法运算)。甚至可能存储空间的节省和顺序扫描中获取的速度增益,可以抵消每次需要进行计算的缺点。最近的PostgreSQL版本还可以使用即时编译(JIT)来使这种表达式更便宜地计算(适用于更大的查询)。
一般而言,最佳策略可能取决于表达式的计算强度。如果强度很高,并且读取行的频率比写入高,那么使用生成列可能是明智之选。
您可以运行一些基准测试并检查差异。在您的情况下,我不认为影响会非常大,最好选择最简单或最易读的实现方式,因为这可以提高可维护性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接