使用表分区进行PostgreSQL性能调优

时间:2018-02-25 11:39:40

标签: postgresql

我正在解决基于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_paymentcash_withdrawlcash_in,...

已知14种交易类型。

通常,有4种类型的查询(最常见的是3和.4):

  1. 选择单个交易,例如:SELECT * FROM jrn.transactions WHERE id = 3748734

  2. 使用JOIN选择单个交易到其他交易,例如:SELECT * FROM jrn.transactions AS m INNER JOIN jrn.transactions AS r ON m.refund_id = r.id WHERE m.id = 3748734

  3. 选择0-100,100-200,..给定类型的交易,如:SELECT * FROM jrn.transactions WHERE account_id = 43784 AND type_id = 'card_payment' LIMIT 100

  4. 多个汇总查询,例如:SELECT SUM(amount), MIN(date_issued), MAX(date_issued) FROM jrn.transactions WHERE account_id = 3748734 AND date_issued >= '2017-01-01'

  5. 在过去的几个月里,我们有意想不到的行数增长,现在是120M。

    我们正在考虑表格分区,以及PostgreSQL doc:https://www.postgresql.org/docs/10/static/ddl-partitioning.html

    选项:

    1. type_id分区表分为14个分区
    2. 将列year和分区表year(或year_month)添加到12个(或144个)分区中。
    3. 我现在正在将数据恢复到测试环境中,我将测试这两个选项。

      对于这种情况,您认为哪种分区规则最合适?还有其他选择吗?

      感谢任何反馈/建议等。

1 个答案:

答案 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);