Postgresql:不断增长的列表的总和

Postgresql:不断增长的列表的总和,postgresql,Postgresql,我有一个从表中选择sum(field),其中boolean_field=true类型的查询 现在大约有800万行,而且只会越来越大 可以理解,Postgres进行seq扫描而不是索引,以避免一次将所有内容加载到内存中 至少我是这样理解的 在任何尺寸下,以可接受的速度跑步的好方法是什么 编辑:版本为Postgres 11.2 EDIT2:已在(boolean\u field)上使用了一个索引,其中boolean\u field=true您可以保留一个包含总和的表: START TRANSACTIO

我有一个
从表中选择sum(field),其中boolean_field=true
类型的查询

现在大约有800万行,而且只会越来越大

可以理解,Postgres进行seq扫描而不是索引,以避免一次将所有内容加载到内存中

至少我是这样理解的

在任何尺寸下,以可接受的速度跑步的好方法是什么

编辑:版本为Postgres 11.2


EDIT2:已在
(boolean\u field)上使用了一个索引,其中boolean\u field=true

您可以保留一个包含总和的表:

START TRANSACTION;

CREATE TABLE table_sum (s double precision NOT NULL);

CREATE FUNCTION upd_sum() RETURNS trigger
   LANGUAGE plpgsql AS
BEGIN
   CASE TG_OP
      WHEN 'INSERT' THEN
         IF NEW.boolean_field THEN
            UPDATE table_sum SET s = s + NEW.field;
         END IF;
         RETURN NEW;
      WHEN 'UPDATE' THEN
         IF NEW.boolean_field OR OLD.boolean_field THEN
            UPDATE table_sum
            SET s = s
                    + CASE WHEN NEW.boolean_field THEN NEW.field ELSE 0.0 END
                    - CASE WHEN OLD.boolean_field THEN OLD.field ELSE 0.0 END;
         END IF;
         RETURN NEW;
      WHEN 'DELETE' THEN
         IF OLD.boolean_field THEN
            UPDATE table_sum SET s = s - OLD.field;
         END IF;
         RETURN OLD;
      WHEN 'TRUNCATE' THEN
         UPDATE table_sum SET s = 0.0;
         RETURN NULL;
   END CASE;
END;$$;

CREATE TRIGGER upd_sum1 AFTER INSERT OR UPDATE OR DELETE ON "table"
   FOR EACH ROW EXECUTE PROCEDURE upd_sum();

CREATE TRIGGER upd_sum2 AFTER TRUNCATE ON "table"
   FOR EACH STATEMENT EXECUTE PROCEDURE upd_sum();

INSERT INTO table_sum
SELECT sum(field) FROM "table"
WHERE boolean_field;

COMMIT;
一些解释:

  • 文档链接,以及

  • 此脚本位于单个事务中,因此计数器在并发事务中正确初始化
    CREATE TRIGGER
    将对表执行
    ACCESS EXCLUSIVE
    锁定,以便在计数器初始化之前阻止所有并发数据访问


您可以保留一个包含总和的表格:

START TRANSACTION;

CREATE TABLE table_sum (s double precision NOT NULL);

CREATE FUNCTION upd_sum() RETURNS trigger
   LANGUAGE plpgsql AS
BEGIN
   CASE TG_OP
      WHEN 'INSERT' THEN
         IF NEW.boolean_field THEN
            UPDATE table_sum SET s = s + NEW.field;
         END IF;
         RETURN NEW;
      WHEN 'UPDATE' THEN
         IF NEW.boolean_field OR OLD.boolean_field THEN
            UPDATE table_sum
            SET s = s
                    + CASE WHEN NEW.boolean_field THEN NEW.field ELSE 0.0 END
                    - CASE WHEN OLD.boolean_field THEN OLD.field ELSE 0.0 END;
         END IF;
         RETURN NEW;
      WHEN 'DELETE' THEN
         IF OLD.boolean_field THEN
            UPDATE table_sum SET s = s - OLD.field;
         END IF;
         RETURN OLD;
      WHEN 'TRUNCATE' THEN
         UPDATE table_sum SET s = 0.0;
         RETURN NULL;
   END CASE;
END;$$;

CREATE TRIGGER upd_sum1 AFTER INSERT OR UPDATE OR DELETE ON "table"
   FOR EACH ROW EXECUTE PROCEDURE upd_sum();

CREATE TRIGGER upd_sum2 AFTER TRUNCATE ON "table"
   FOR EACH STATEMENT EXECUTE PROCEDURE upd_sum();

INSERT INTO table_sum
SELECT sum(field) FROM "table"
WHERE boolean_field;

COMMIT;
一些解释:

  • 文档链接,以及

  • 此脚本位于单个事务中,因此计数器在并发事务中正确初始化
    CREATE TRIGGER
    将对表执行
    ACCESS EXCLUSIVE
    锁定,以便在计数器初始化之前阻止所有并发数据访问


没有单一的解决方案。一种选择是预先计算部分和。也许每天都有。示例:每天,对当天的新记录求和,并写入不同的表。然后做一个
从day_表中选择sum(field)
,这会快得多。哪个Postgres版本?当前版本可以为一个查询生成多个线程,如果您的服务器硬件能够处理的话,这可以加快类似的速度that@a_horse_with_no_nameverion 11.2仍然很慢,有多少行符合where条件?也许过滤索引有帮助
在_表(字段)上创建索引,其中布尔_字段
@a_horse_,如最初所述,约为800万。已经在使用部分索引和调用的确切条件。没有单一的解决方案。一种选择是预先计算部分和。也许每天都有。示例:每天,对当天的新记录求和,并写入不同的表。然后做一个
从day_表中选择sum(field)
,这会快得多。哪个Postgres版本?当前版本可以为一个查询生成多个线程,如果您的服务器硬件能够处理的话,这可以加快类似的速度that@a_horse_with_no_nameverion 11.2仍然很慢,有多少行符合where条件?也许过滤索引有帮助
在_表(字段)上创建索引,其中布尔_字段
@a_horse_,如最初所述,约为800万。已经在使用带有调用确切条件的部分索引。