不断增加的列的总和

uld*_*all 5 postgresql

我有一个“交易”表,其中每笔交易都有一个金额:http : //sqlfiddle.com/#!15/42849/1

表中的记录永远不会被删除或更新。仅添加新交易。

我想计算金额的总和。对于每个请求,计算不必是 100% 最新的。

在大约一百万行的数据集上,这在我的数据库上大约需要 400 毫秒。这对于我的应用程序来说太慢了,我正在尝试找到加快速度的最佳解决方案。

到目前为止我尝试过的

  1. 物化视图:增加了必须运行 cronjob 的复杂性,它每 X 秒更新一次视图。
  2. 在应用服务器上缓存:当缓存需要更新时,每个 X 请求都会很慢。
  3. 存储对旧子集的查询结果:存储先前请求的 SUM 并使用这些来计算正确的总数。增加了复杂性。

PostgreSQL 是否提供了加速此类查询的解决方案?

更新 1

SUM 查询只是单列上的基本总和,所以我不相信这个查询本身可以变得更快。解决方案可能是进行某种缓存/预计算或类似操作。PostgreSQL 在这方面有什么特点吗?

更新 2

有问题的表:

CREATE TABLE transactions
(
  id bigserial NOT NULL,
  amount bigint NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

有问题的查询:

SELECT SUM(amount) FROM transactions;
Run Code Online (Sandbox Code Playgroud)

更新 3

我发现我实际上也需要一个“类型”。

更新表:

CREATE TABLE transactions
(
  id bigserial NOT NULL,
  amount bigint NOT NULL,
  type int NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

更新的查询:

SELECT SUM(amount) FROM transactions GROUP BY type;
Run Code Online (Sandbox Code Playgroud)

SQL 小提琴:http ://sqlfiddle.com/#!15/77e67/2

Len*_*art 2

您可以评估以下一个想法:

\n\n
CREATE TABLE last_transaction\n(    last_id bigserial NOT NULL\n,    cumulative_amount bigint NOT NULL\n);  \n\nINSERT INTO last_transaction (last_id, cumulative_amount) VALUES (-1,0);\n
Run Code Online (Sandbox Code Playgroud)\n\n

当前金额应该类似于:

\n\n
SELECT coalesce(SUM(t.amount),0) + coalesce(lt.cumulative_amount,0) \nFROM transactions t\nRIGHT JOIN last_transaction lt\n    ON t.id > lt.last_id\nGROUP BY lt.cumulative_amount;\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以定期刷新last_transaction,类似于:

\n\n
update last_transaction\n    set last_id = (select max(id) from transactions)\n      , cumulative_amount = (select sum(amount) from transactions);\n
Run Code Online (Sandbox Code Playgroud)\n\n

你的fiddle中的PostgreSQL版本不支持(也许没有版本支持?)

\n\n
set (last_id, cumulative_amount) = (select ...)\n
Run Code Online (Sandbox Code Playgroud)\n\n

只是一个想法,可能适合也可能不适合您的需求。

\n\n

编辑:添加类型

\n\n

如果要包含一个类型(考虑将其命名为 transaction_type 或类似的名称),我们可以扩展 last_transaction:

\n\n
CREATE TABLE last_transaction\n(    type int not null\n,    last_id bigserial NOT NULL\n,    cumulative_amount bigint NOT NULL\n,        constraint pk_last_transaction primary key (type)\n);  \n\nINSERT INTO last_transaction (type, last_id, cumulative_amount) \nSELECT distinct type, -1, 0\nFROM transactions;\n
Run Code Online (Sandbox Code Playgroud)\n\n

要获取 current_amount,我们需要向GROUP BY子句以及ON子句添加类型。

\n\n
SELECT lt.type\n     , coalesce(SUM(t.amount),0) + coalesce(lt.cumulative_amount,0) \nFROM transactions t\nRIGHT JOIN last_transaction lt\n    ON t.id > lt.last_id\n   AND t.type = lt.type\nGROUP BY lt.type, lt.cumulative_amount;\n
Run Code Online (Sandbox Code Playgroud)\n\n

要对last_transaction进行完全刷新(根据@Andriy M建议):

\n\n
UPDATE last_transaction AS lt\n    SET last_id = t.last_id\n      , cumulative_amount = t.cumulative_amount\nFROM (\n    SELECT TYPE\n         , MAX(id)\n         , SUM(amount)\n    FROM transactions\n    GROUP BY TYPE\n) AS t (type, last_id, cumulative_amount)\nWHERE t.type = lt.type;\n
Run Code Online (Sandbox Code Playgroud)\n\n

我尚未检查 @YperSillyCube\xe1\xb5\x80\xe1\xb4\xb9 建议。

\n\n

我向事务表添加了大约一百万行以及我认为相关的索引,但 sqlfiddle 中的计划看起来有点令人失望。

\n