我应该对我的 postgres 表进行分区吗?

Should I partition my postgres tables?

我将一些股票数据存储在 Postgres 9.5 数据库中,我的 table 的格式如下,主键为(日期时间,符号):

symbol (varchar[30]),
datetime (timestamptz),
value (double precision) 

现在,我的一些较大的 table 超过 8000 万行,因此,一些查询比我希望的要慢一些。我 99% 的查询都涉及为特定交易品种获取一天的数据,例如:

SELECT * from "prices" 
WHERE symbol = 'AAPl' AND datetime between '2016-07-22 9:30' AND '2016-07-22 16:30'

我平均每天会插入 25 万行,但在某些高峰期它可能会高达 50 万行。这是美国市场开盘的6.5小时

我正在阅读分区并考虑每月进行一次(平均一个月有 20 个交易日,每个分区我应该有 5 到 1000 万行)

我在数据库方面没有经验,到目前为止我所设置的是新手的工作。当我研究编写自动分区脚本时,它们似乎有某种类型的查询来搜索分区是否存在。以下内容摘自位于 https://blog.engineyard.com/2013/scaling-postgresql-performance-table-partitioning

的更长的函数
PERFORM 1
FROM   pg_catalog.pg_class c
JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE  c.relkind = 'r'
AND    c.relname = _tablename
AND    n.nspname = 'myschema';

我真的不想每天检查 table 是否存在 250k 到 500k 次所以我想我可以 运行 一个 cron 作业来创建 table 每月一次,然后就不用为支票烦恼了?

我也在想,也许我应该将我所有的数据插入到一个临时的 table 中,然后 运行 在 4:30pm 市场收盘后的一个 cron 作业中,因为没有数据一旦市场收盘就被插入。我的想法是我的 cron 作业会清空临时文件 table 并将所有内容放入正确的分区。

这值得吗?我应该研究分片吗?数据库服务器是一个 i7 6 核处理器,具有 64 g 内存和存储在 SSD 驱动器上的数据。我可以在同一台服务器上启动更多 postgres 实例,但我无权访问更多服务器,因此 postgres 实例必须位于同一台服务器上。

此外,当我在这里时,我应该对 table 的索引提出任何建议,以使我的上述查询更快?

谢谢!

在您的场景中可以进行分区吗?

PostgreSQL partitioning is built on table inheritance. Before you proceed any further you need to be aware of this limitation of inheritance.

A serious limitation of the inheritance feature is that indexes (including unique constraints) and foreign key constraints only apply to single tables, not to their inheritance children. This is true on both the referencing and referenced sides of a foreign key constraint.

如果你有幸没有外键,是的分区可以利用。

分区

我不知道您在网上阅读了哪些内容,但如果您阅读 official documentation,分区就很简单了。嗯,对于新的 table 来说也是如此。对于旧的 tables 它有点棘手。我对付旧 table 的策略是这样的(可能不是最好的):

1) 创建新的table 像旧的table;
2) 在 newtable
上创建分区 3) 将数据移入newtable
4) 删除旧的 table 并用视图
替换它 5) 创建触发器使视图 writable(这是非常标准的,您可以在文档中找到示例)

不要创建太多分区,一个月一个是合理的。

标准化

这不是分区的替代方法。这是你应该认真考虑的事情。您有一个 symbol varchar(30) 为什么不创建一个名为 symbols 的 table 并将它们全部放在那里?那么你在这个 table 中只有一个 int 字段。假设平均符号长度为 10,您将在 table 中为每条记录削减 6 个字节。索引也会缩小,这有帮助。

双精度到整数

另一个优化是从 double 切换到 int,这将节省另外 4 个字节(您必须以次要货币格式存储价格)。有了这个和以上,我们已经减少了至少 30% 的 tables 大小!

手动table拆分

I was also thinking that maybe I should just insert all of my data into a temporary table and then run a cron job after the market closes at 4:30pm as no data gets inserted once the market closes.

差不多,但不完全是。将所有内容插入主 table。市场收盘后,使用 cron 作业将超过 30 天的数据移动到存档中 table.

总结Table

跟踪长期趋势时,您只需要最高价、最低价、收盘价和开盘价,不需要日内波动。使用此数据(由您的 cron 填充)创建摘要 table,并将其用于趋势分析。仅将主要 table 用于日内或短期趋势。