我想将用户设置存储在Postgresql数据库中。 我想保留其设置的完整历史记录,并且还能够查询给定用户的最新设置。
我尝试将设置存储在这样的表中:
CREATE TABLE customer (
customer_id INTEGER PRIMARY KEY,
name VARCHAR NOT NULL
);
CREATE TABLE customer_settings (
customer_id INTEGER REFERENCES customer NOT NULL,
sequence INTEGER NOT NULL, -- start at 1 and increase, set by the application
settings JSONB NOT NULL,
PRIMARY KEY(customer_id, sequence)
);
因此,customer_settings是每个客户的仅追加日志。
然后查询最新设置,我使用了一个长查询,它将执行一个子查询来为给定的sequence
选择最大值customer_id
,然后为该ID选择设置。
这很尴尬!我想知道是否有更好的方法?我可以使用视图还是触发器来创建第二张表latest_customer_settings
??
答案 0 :(得分:2)
您可以进行查看。要获得Postgres中多个客户的设置,我建议:
select distinct on (customer_id)
from customer_settings cs
order by customer_id, sequence desc;
对于此查询,我建议在customer_settings(customer_id, sequence desc)
上添加一个索引。
此外,如果可以为所有客户处理一个总的序列号,则可以让Postgres生成序列。
CREATE TABLE customer_settings (
customer_settings_id bigserial primary key,
customer_id INTEGER REFERENCES customer NOT NULL,
settings JSONB NOT NULL
);
然后,应用程序不需要设置sequence
号。您只需将customer_id
和settings
插入表中即可。
让应用程序维护此信息有一些缺点。首先,应用程序必须先读取数据库,然后才能将任何内容插入表中。其次,如果多个线程同时更新表(在这种情况下,是同一位客户),则可以具有竞争条件。
答案 1 :(得分:0)
您可以使用row_number()
窗口功能,它将帮助您获取每个客户的最新设置
with cte as (select cs.*,
row_number() over(partition by c.customer_id order by sequence desc) rn
from customer c join customer_settings cs on c.customerid=cs.customerid
) select * from cte where rn=1
答案 2 :(得分:0)
假设您只需要给定用户的最新日志,并且假设sequence
一直在增加并且是唯一的,那么实际上您只需要一个简单的查询:
SELECT *
FROM customer_settings
WHERE customer_id = 123
ORDER BY sequence DESC
LIMIT 1;
如果您想花一些时间来创建更好的日志记录框架,请尝试研究MDC之类的东西(映射诊断上下文,see here)。使用MDC,每个日志语句都使用完全唯一的标识符写出,该标识符也将在响应头或正文中发送。然后,将后端与前端或使用者之间的异常关联起来变得容易又万无一失。