我有一个“交易”表,其中每笔交易都有一个金额:http : //sqlfiddle.com/#!15/42849/1
表中的记录永远不会被删除或更新。仅添加新交易。
我想计算金额的总和。对于每个请求,计算不必是 100% 最新的。
在大约一百万行的数据集上,这在我的数据库上大约需要 400 毫秒。这对于我的应用程序来说太慢了,我正在尝试找到加快速度的最佳解决方案。
到目前为止我尝试过的
题
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
您可以评估以下一个想法:
\n\nCREATE 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\nSELECT 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\nupdate 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\nset (last_id, cumulative_amount) = (select ...)\n
Run Code Online (Sandbox Code Playgroud)\n\n只是一个想法,可能适合也可能不适合您的需求。
\n\n编辑:添加类型
\n\n如果要包含一个类型(考虑将其命名为 transaction_type 或类似的名称),我们可以扩展 last_transaction:
\n\nCREATE 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
子句添加类型。
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\nUPDATE 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 归档时间: |
|
查看次数: |
689 次 |
最近记录: |