Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 使列值保持最新的最佳方法_Postgresql_Triggers - Fatal编程技术网

Postgresql 使列值保持最新的最佳方法

Postgresql 使列值保持最新的最佳方法,postgresql,triggers,Postgresql,Triggers,我有以下表格(简化): 它们通过外键(元素\ id)连接。如果某个元素的所有采集条目的交付时间大于28,则该元素将获得“关键”状态。目前我使用的是一个视图 基于elements表,该表检查每个element_id是否为关键元素。我使用的函数读取元素的最小值(dilvery_time),并检查它是否大于28。每次打开视图时都会执行此计算 这个练习很有效,但是很慢。此外,我认为上面的方法做了很多不必要的工作,因为只有在修改表获取时,临界状态才能改变 我的新方法是在elements表中添加一个布尔

我有以下表格(简化):

它们通过外键(元素\ id)连接。如果某个元素的所有采集条目的交付时间大于28,则该元素将获得“关键”状态。目前我使用的是一个视图 基于elements表,该表检查每个element_id是否为关键元素。我使用的函数读取元素的最小值(dilvery_time),并检查它是否大于28。每次打开视图时都会执行此计算

这个练习很有效,但是很慢。此外,我认为上面的方法做了很多不必要的工作,因为只有在修改表获取时,临界状态才能改变

我的新方法是在elements表中添加一个布尔列“critical”。此外,我还将在采集表上设置一个触发函数,用于更新修改元素的关键状态(如有必要)。然后,关键状态应该始终是最新的,并且选择应该快得多

我的新方法合适吗?还是有更好的方法来解决我的问题

编辑,以下是表、视图和函数的创建状态:

CREATE TABLE elements (
element_id serial primary key,
elemnt_name varchar(100));

CREATE TABLE acquisitions (
acquisition_id serial primary key,
element_id int NOT NULL,
delivery_time int,
foreign key (element_id) references elements(element_id));

CREATE OR REPLACE FUNCTION is_element_critical(param integer)
RETURNS boolean AS
$BODY$
DECLARE
delivery_date_int integer;
BEGIN
SELECT into delivery_date_int min(delivery_time) 
from acquisitions where   element_id  = param;
IF delivery_date_int > 28 THEN
RETURN true;
ELSE
return false;
END IF;
END
$BODY$
LANGUAGE plpgsql VOLATILE;

CREATE OR REPLACE VIEW elementview AS 
SELECT elements.element_id,
elements.elemnt_name, is_element_critical(elements.element_id)  
AS is_element_critical
FROM elements;

对于约10000次采集和约1500个元素,elementview上的选择需要1600毫秒。

您的方法的一个问题是对视图中的每一行计算函数

您可以尝试使用连接,并以基于集合的方式处理该连接(这通常是比逐行处理更好的方法)

采集(元素id、交付时间)
上添加索引可能会加快此查询的速度

如果您没有每个元素的采集,您可能希望将其更改为
左连接

如果非关键采集的数量远低于关键采集的数量,则可以使用部分索引进一步加快采集速度:

create index idx_ac on acquisitions (element_id, delivery_time)
  where delivery_time > 28;
然后仅针对关键收购加入:

SELECT e.element_id, 
       e.elemnt_name, 
       min(a.delivery_time) > 28 as is_element_critical
FROM elements e
  LEFT JOIN acquisitions a ON a.element_id = e.element_id and a.delivery_time > 28
GROUP BY e.element_id, e.elemnt_name;
由于添加了条件
和a.delivery\u time>28
,因此需要左连接


在我的笔记本电脑上,第一次查询需要35毫秒(2000个元素,30000次采集)。第二个在5毫秒内运行。每个元素都至少有一个关键的采集(这可能不是真正现实的)

与其发布一些GUI的屏幕截图,不如发布这些表的
CREATE TABLE
语句。或者更好:创建一个关于您可能还想发布您现在使用的查询的示例,也许它可以改进(有关如何发布性能问题的一些提示,请参见此处:)您正在谈论非规范化。尽量避免。如果可能的话,更愿意寻求改进而不是查询。也许发布查询并问“为什么速度慢”——也许有一个简单的改进可以加快速度。我想应该是min(a.delivery_time),而不是min(e.delivery_time)。@akkusativeobjekt:是的,这是一个打字错误。请看我的编辑。还有更大的改进空间(但这取决于数据)。我测试了您的第一种方法,只花了100毫秒,这是一个很好的结果(我添加了另一个连接,使所有列都像旧视图中的一样)。是的,关键元素比非关键元素少得多。我将尝试使用索引的方法。我误读了,关键元素比非关键元素少得多。我可以颠倒索引的语句吗?@akkusativeobjekt:我会保持列的顺序不变(因为这有助于连接)。在这种情况下,您可能不需要
where
子句。但一定要仔细研究一下,并检查一下执行计划:它会告诉你哪种索引策略更有效。
SELECT e.element_id, 
       e.elemnt_name, 
       min(a.delivery_time) > 28 as is_element_critical
FROM elements e
  LEFT JOIN acquisitions a ON a.element_id = e.element_id and a.delivery_time > 28
GROUP BY e.element_id, e.elemnt_name;