PostgreSQL:使用另一列的聚合值加速更新列

问题描述 投票:0回答:1

我使用PostGIS,数据相当大,大约有15亿行,我有一个网格表及其行政区域,我需要获取一个值,即特定行政区域的居民数量以进行进一步计算。我采取的步骤是创建一个 sum_residents 列,并用按行政区域名称分组的居民总数(adm_col1、adm_col2、adm_col3)

我运行的查询:

UPDATE table_grid AS gd
SET sum_resident_grid = subquery.total_sum
FROM (
     SELECT adm_col1, adm_col2, adm_col3, SUM(resident_grid) AS total_sum
     FROM table_grid
     GROUP BY adm_col1, adm_col2, adm_col3
) AS subquery
WHERE gd.adm_col1 = subquery.adm_col1
AND gd.adm_col2 = subquery.adm_col2
AND gd.adm_col3 = subquery.adm_col3;

最初对于比较小的数据,查询是没有问题的,但是当数据非常大的时候,查询的时间就非常长,可能需要一天多的时间。有没有更快的方法来获取 sum_resident_grid 值?

第二阶段: 得到sum_resident_grid后,我实际上是用这个值进行加权计算,其中公式为resident_grid/sum_resident_grid*actual_resident_value 通过加入管理表获得,我运行的查询:

UPDATE table_grid AS gd
SET
  sum_income = ROUND(gd.resident_grid::float/gd.sum_resident_grid*de.actual_resident_value)::float/de.actual_resident_value*de.total_inco ,
  sum_expend = ROUND(gd.resident_grid::float/gd.sum_resident_grid*de.actual_resident_value)::float/de.actual_resident_value*de.total_expe ,
  resident_grid = ROUND(gd.resident_grid::float/gd.sum_resident_grid*de.actual_resident_value)
FROM table_administrative de
WHERE gd.sum_resident_grid !=0
AND gd.adm_code1 = de.adm_code1;

那么有没有其他方法可以加快我正在运行的查询速度?预先感谢您的帮助!

sql postgresql postgis
1个回答
0
投票

这个答案主要旨在提供一种通用方法,可以减轻进行昂贵的全表聚合/求和的需要。您可以考虑保留运行求和,而不是执行当前查询。每次将新记录插入到

table_grid
表中时,您都可以更新运行总计。在 Postgres 中,您可以通过触发器来完成此操作:

-- assumes a "table_grid_total" table already exists

CREATE OR REPLACE FUNCTION table_grid_insert_trigger_fnc()
RETURNS trigger AS
$$

BEGIN

UPDATE table_grid_total
SET total = total + NEW.resident_grid
WHERE adm_col1 = NEW.adm_col1 AND
      adm_col2 = NEW.adm_col2 AND
      adm_col3 = NEW.adm_col3;

RETURN NEW;
END;

$$

LANGUAGE 'plpgsql';

CREATE TRIGGER table_grid_insert_trigger

AFTER INSERT ON table_grid

FOR EACH ROW

EXECUTE PROCEDURE table_grid_insert_trigger_fnc();

换句话说,对于

table_grid
表的每次插入,我们都会为每个
resident_grid
元组保留
(adm_col1, adm_col2, adm_col3)
的运行总计。要访问这些总和,您只需随时查询
table_grid_total
表即可。

© www.soinside.com 2019 - 2024. All rights reserved.