Postgresql以FIFO方式限制表行
我有一个带有PK id、两个FK、两个其他id和一个时间戳的表。 我希望对该表有一个限制,以便每个FK的组合只能有有限的行数。 例如,如果有10多行具有相同的FK,则应删除时间戳中最早的一行 目前,解决方案idea是插入前的触发器,它应该检查表中是否有多个行与要插入的行具有相同的FK。如果存在最早的一个字段,则应删除时间戳Postgresql以FIFO方式限制表行,sql,postgresql,Sql,Postgresql,我有一个带有PK id、两个FK、两个其他id和一个时间戳的表。 我希望对该表有一个限制,以便每个FK的组合只能有有限的行数。 例如,如果有10多行具有相同的FK,则应删除时间戳中最早的一行 目前,解决方案idea是插入前的触发器,它应该检查表中是否有多个行与要插入的行具有相同的FK。如果存在最早的一个字段,则应删除时间戳 有人能帮我实现这一点吗?您应该使用一个单独的汇总表,由触发器维护,其中将包含列fk1、fk2和带有检查计数的计数此问题的替代解决方案是使用数组列而不是行和插入到。。。关于冲突
有人能帮我实现这一点吗?您应该使用一个单独的汇总表,由触发器维护,其中将包含列fk1、fk2和带有检查计数的计数此问题的替代解决方案是使用数组列而不是行和插入到。。。关于冲突更新。。。支持 在线示例: 结构: 创建表测试 id串行主键, fk_1整数不为空, fk_2整数不为空, 最新时间戳[]不为空 ; 在test_rr fk_1、fk_2上创建唯一索引idx_UNIQUE_rr; 升级数据: 插入测试单元rr fk_1,fk_2,最新版本 值1、2、数组[当前\u时间戳] 在冲突fk_1上,fk_2 DO UPDATE SET latest=array_catEXCLUDED.latest,test_rr.latest[:10]; 选择条目: 从测试rr中选择id、fk_1、fk_2、unnestlatest作为ts,其中fk_1=1和fk_2=2; …导致:
id | fk_1 | fk_2 | ts
-----+------+------+-------------------------------
652 | 1 | 2 | 2019-03-10 13:28:57.806489+01
652 | 1 | 2 | 2019-03-10 13:28:56.670678+01
652 | 1 | 2 | 2019-03-10 13:28:55.470668+01
652 | 1 | 2 | 2019-03-10 13:28:54.174111+01
652 | 1 | 2 | 2019-03-10 13:28:52.878719+01
652 | 1 | 2 | 2019-03-10 13:28:51.3748+01
652 | 1 | 2 | 2019-03-10 13:28:49.886457+01
652 | 1 | 2 | 2019-03-10 13:28:48.190317+01
652 | 1 | 2 | 2019-03-10 13:28:46.350833+01
652 | 1 | 2 | 2019-03-10 13:11:50.506323+01
(10 rows)
您还可以创建自己的类型来支持更多列,而不是timestamptz[]
创建类型my_entry_data作为ts timestamptz,data varchar;
创建表测试
id串行主键,
fk_1整数不为空,
fk_2整数不为空,
最新my_条目_数据[]不为空
;
在test_rr fk_1、fk_2上创建唯一索引idx_UNIQUE_rr;
- ...
插入测试单元rr fk_1,fk_2,最新版本
值1,2,数组[当前\u时间戳,'L'::我的\u条目\u数据]
在冲突fk_1上,fk_2不更新
SET latest=array_catEXCLUDED.latest,test_rr.latest[:10];
选择id、fk_1、fk_2、tmp.ts、tmp.data
从test_rr,unTestLatest AS tmp-横向功能调用
式中,fK_1=1,fK_2=2;
然而,负载测试必须显示这是否比触发器或其他方法更快。至少这样做的好处是,行只会被更新,而不会被插入和删除,这可能会节省一些I/O。如果应用程序错误导致它很快添加大量坏行,该怎么办?你过去的历史很快就会消失。此外,删除更新触发器中的数据会使更新速度变慢。最好将清除旧数据作为一个批处理过程实现,并进行一些审核,甚至可能在某处备份旧行。不幸的是,PostgreSQL没有实现它,也没有任何其他企业RDBMS产品。最大的症结是会绊倒你的:并发性。例如,您的表有十行,两个用户同时尝试插入一行。现在,两个会话都将尝试删除最旧的行:哦!所以您需要序列化对表的DML访问。我应该解释一下,我确信当时只有一个用户在写,因为后端应用程序正在处理这个问题。为什么您需要限制逻辑存储的行?我宁愿使用行限制视图,例如,如果出于性能原因需要,则执行周期清理。任何直接在编写事务时工作的解决方案在高负载下都会有严重的性能损失。如果你的数据是时间序列,你也可以考虑与一个扩展插件集成在一起,这样可以让你在写和读性能上得到很大的提升。2不需要触发器;视图实际上可以隐藏实现。只是在使用自定义复合类型时用一个示例进行了更新。