保持列值最新的最佳方法

时间:2014-03-27 10:46:21

标签: postgresql triggers

我有以下表格(简化):
enter image description here

enter image description here

它们与外键(element_id)连接。如果元素的所有获取条目的delivery_time都大于28,则该元素的状态为critical。目前我使用的是一个视图 基于元素表,如果它是关键的,则检查每个element_id。我使用的函数读出元素的min(dilvery_time)并检查它是否大于28.每次打开视图时都会进行此计算。

溶质有效,但速度很慢。另外我认为上面的方法做了很多不必要的工作,因为只有在修改了表格获取时,关键状态才会改变。

我的新方法是在元素表中添加一个布尔列“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上的select需要1600 ms。

1 个答案:

答案 0 :(得分:2)

您的方法的一个问题是为视图中的每一行评估函数。

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

CREATE OR REPLACE VIEW elementview 
AS 
SELECT e.element_id, 
       e.elemnt_name, 
       min(a.delivery_time)  > 28 as is_element_critical
FROM elements e
  JOIN acquisitions a ON a.element_id = e.element_id
GROUP BY e.element_id, e.elemnt_name;

acquisitions(element_id, delivery_time)上添加索引可能会加快此查询速度。

如果您没有为每个元素进行采集,则可能需要将其更改为LEFT JOIN

如果不重要的收购数量远远低于关键收购数量,那么您可以使用部分索引进一步加快收购速度:

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;

由于添加条件and a.delivery_time > 28,左连接是必需的。

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