【发布时间】:2018-02-25 22:26:45
【问题描述】:
我正在解决基于 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选择单个事务并加入其他事务,例如:
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'
在过去的几个月里,我们的行数出现了意想不到的增长,现在达到了 1.2 亿。
我们正在考虑表分区,遵循 PostgreSQL 文档:https://www.postgresql.org/docs/10/static/ddl-partitioning.html
选项:
-
type_id将表分区为 14 个分区 - 将
year列和year(或year_month)分区表添加到12(或144)个分区中。
我现在正在将数据恢复到测试环境中,我将测试这两个选项。
对于这种情况,您认为最合适的分区规则是什么?还有其他选择吗?
感谢任何反馈/建议等。
【问题讨论】:
-
如果查询 3 和 4 是最频繁的,我们应该尝试优化它们的分区。他们的
WHERE条件包括三列account_id、type_id和date_issued。account_id的选择性非常高,因此它很可能应该更好地用于索引。date_issued与不相等的运算符一起使用,因此分区不会有太大帮助。type_id没有选择性,所以可以,但没有在查询 4 中使用。==> 没有明显的解决方案(至少对我来说)。 -
请注意,您指的是 Postgresql 10 的文档,而您的服务器是 9.6。
-
在选项 2 上:由于查询 4 不包含
year(或year_mongth),这也无济于事。无论如何,查询 3 不受 w.r.t 限制。date_issued,所以这也不是最佳解决方案。 -
我目前正在考虑物化视图的方向(例如,用于处理 4 号聚合查询)。 @Luke1988:
jrn.transactions的更新/插入频率是多少?查询 4 中sum(amount)的准确性有多重要? -
是的,因为它们是最重要的外键。结合其中一个日期字段,它们几乎构造了表格的自然键。
标签: postgresql