我们正在实现一个电子商务数据模型,并在postgres生成的列、hasura计算字段和postgres视图之间进行决策。
作为简化,我们有两个表:
items
------------
id
order_id
unit_price
quantity
orders
------------
id
我们现在要添加 total_price
到 items
表( unit_price * quantity
),和 total_price
服从命令( sum
的 total_price
最重要的 items
按顺序)。
在第一种情况下,我们使用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计算场解的缺点是 total_price
仅在graphql查询中公开,因此不能在sql中使用它。
乍一看,postgresview解决方案似乎没有任何问题。
我们错过什么了吗?
为什么要在postgres生成的字段或视图上使用hasura计算字段?
是否有一个比较表或流程图可以帮助我们决定哪种方法在每个特定情况下是最好的?
最后,对于所有这些,我们当然也可以使用postgres触发器、hasura事件触发器和hasura操作。。。什么时候才是合适的解决方案?
干杯!
1条答案
按热度按时间lokaqttq1#
对于这个特定的例子,我将使用postgresql视图,因为所涉及的计算非常便宜(一次乘法)。它甚至可能是存储空间的节省和在顺序扫描中产生的速度增益超过了在需要值时必须执行计算的缺点。最近的postgresql版本也可以使用即时编译(just-in-time compilation,jit)来降低此类表达式的计算成本(对于较大的查询)。
一般来说,最佳策略可能取决于表达式的计算强度。如果这个值很高,而且行的读写频率更高,那么使用生成的列可能是有意义的。
您可以运行一个小基准测试并检查差异。在您的情况下,我认为影响不会很大,最好选择最简单或可读性最好的实现,因为这样可以提高可维护性。