我正在解决基于PostgreSQL 9.6 dbo的系统的性能问题。介绍:
12yo系统,类似于银行系统,大多数查询的主表称为transactions
。
CREATE TABLE jrn.transactions (
ID BIGSERIAL,
type_id VARCHAR(200),
account_id INT NOT NULL,
date_issued DATE,
date_accounted DATE,
amount NUMERIC,
..
)
在表transactions
中,我们将所有交易存储在银行帐户中。字段type_id
确定事务的类型。服务器也作为C#EntityFramework Discriminator列。值如下:
card_payment
,cash_withdrawl
,cash_in
,...
已知14种交易类型。
通常,有4种类型的查询(最常见的是3和.4):
选择单个交易,例如:SELECT * FROM jrn.transactions WHERE id = 3748734
使用JOIN选择单个交易到其他交易,例如:SELECT * FROM jrn.transactions AS m INNER JOIN jrn.transactions AS r ON m.refund_id = r.id WHERE m.id = 3748734
选择0-100,100-200,..给定类型的交易,如:SELECT * FROM jrn.transactions WHERE account_id = 43784 AND type_id = 'card_payment' LIMIT 100
多个汇总查询,例如:SELECT SUM(amount), MIN(date_issued), MAX(date_issued) FROM jrn.transactions WHERE account_id = 3748734 AND date_issued >= '2017-01-01'
在过去的几个月里,我们有意想不到的行数增长,现在是120M。
我们正在考虑表格分区,以及PostgreSQL doc:https://www.postgresql.org/docs/10/static/ddl-partitioning.html
选项:
type_id
分区表分为14个分区year
和分区表year
(或year_month
)添加到12个(或144个)分区中。我现在正在将数据恢复到测试环境中,我将测试这两个选项。
对于这种情况,您认为哪种分区规则最合适?还有其他选择吗?
感谢任何反馈/建议等。
答案 0 :(得分:2)
分区对这些查询非常有帮助,因为除非您忘记索引,否则他们不会执行顺序扫描。
我看到分区的唯一好处是,如果你想有效地删除旧行;然后按日期分区是最好的。
根据您的查询,您应该拥有这些索引(除了主键索引):
CREATE INDEX ON jrn.transactions (account_id, date_issued);
CREATE INDEX ON jrn.transactions (refund_id);
如果您可以牺牲一些插入性能以尽可能快地进行第三次查询(您可能想要测试),则以下索引可能是个好主意:
CREATE INDEX ON jrn.transactions (account_id, type_id);