如何加快postgres中大表的SUM查询速度

abi*_*ips 8 sql database postgresql

问题

我正在尝试在 postgres 数据库中的 SQL 视图上运行以下查询:

SELECT sum(value) FROM invoices_view;

大约有invoices_view4500 万行,整个数据库的数据大小为 40.5 GB,数据库有 61 GB RAM。

目前这个查询需要 4.5 秒,我希望它最好低于 1 秒。

我尝试过的事情

当然,我不能直接向 SQL 视图添加索引,但可以在基础表上有一个索引:

CREATE INDEX invoices_on_value_idx ON invoices (value);

我还在VACUUM ANALYZE发票表上运行了一个。

解释分析

的输出EXPLAIN ANALYZE如下:

EXPLAIN (ANALYZE, BUFFERS) SELECT sum(value) FROM invoices_view;
Finalize Aggregate  (cost=1514195.47..1514195.47 rows=1 width=32) (actual time=5102.805..5102.806 rows=1 loops=1)
  Buffers: shared hit=14996 read=1446679
  I/O Timings: read=3235.147
  ->  Gather  (cost=1514195.16..1514195.47 rows=3 width=32) (actual time=5102.716..5109.229 rows=4 loops=1)
        Workers Planned: 3
        Workers Launched: 3
        Buffers: shared hit=14996 read=1446679
        I/O Timings: read=3235.147
        ->  Partial Aggregate  (cost=1513195.16..1513195.17 rows=1 width=32) (actual time=5097.626..5097.626 rows=1 loops=4)
              Buffers: shared hit=14996 read=1446679
              I/O Timings: read=3235.147
              ->  Parallel Seq Scan on invoices  (cost=0.00..1505835.14 rows=14720046 width=6) (actual time=0.049..3734.495 rows=11408036 loops=4)
                    Buffers: shared hit=14996 read=1446679
                    I/O Timings: read=3235.147
Planning Time: 2.503 ms
Execution Time: 5109.327 ms
Run Code Online (Sandbox Code Playgroud)

有谁知道我如何才能加快速度?或者我现在应该寻找 postgres 的替代品?

更多详情

这是我需要在数据集上运行的查询的最简单版本。

例如,我需要能够根据用户输入进行求和,即附加 WHERE 子句和 GROUP BY。

保持运行总计只能解决这个最简单的情况。

Tim*_*sen 6

您应该考虑使用触发器来跟踪滚动总和:

CREATE OR REPLACE FUNCTION func_sum_invoice()
RETURNS trigger AS
$BODY$
BEGIN
    UPDATE invoices_sum
    SET total = total + NEW.value;
RETURN NEW;
END;
$BODY$
Run Code Online (Sandbox Code Playgroud)

然后使用此函数创建触发器:

CREATE TRIGGER sum_invoice
AFTER INSERT ON invoices
FOR EACH ROW
EXECUTE PROCEDURE func_sum_invoice();
Run Code Online (Sandbox Code Playgroud)

现在,每次插入表中invoices都会触发一个触发器来计算滚动总和。要获得该总和,现在您只需要一次选择,这应该非常快:

SELECT total
FROM invoices_sum;
Run Code Online (Sandbox Code Playgroud)