我有以下表格(简化):
它们与外键(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。
答案 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内运行。每个元素至少有一个关键的采集(可能不太现实)