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万。已经在使用带有调用确切条件的部分索引。