我应该分区我的postgres表吗?

时间:2016-07-23 22:32:46

标签: database postgresql postgresql-performance

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

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

现在,我的一些较大的表超过8000万行,因此,有些查询比我想要的慢一些。 99%的查询都涉及为特定符号抓取一天的数据,例如:

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

平均每天我会插入250k行,但在某些spikey天,它可以高达50万行。这是美国市场开放的6.5小时

我正在阅读分区并考虑每月进行分区(一个月平均20个交易日,每个分区应该有500到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';

我真的不想检查表格是否每天存在250k到500k次,所以我想我可以运行一个cron作业来按月创建表格然后不打扰检查?

我还在想,也许我应该将所有数据插入临时表,然后在市场收盘后于下午4:30运行cron作业,因为市场收盘后没有数据插入。我的想法是,我的cron作业将清空临时表并将所有内容放入正确的分区。

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

另外,当我在这里的时候,我在桌子上应该有哪些关于索引的建议来使我的查询变得更快?

谢谢!

1 个答案:

答案 0 :(得分:2)

您的方案中是否可以进行分区?

Postgresql partitioning建立在表继承之上。在继续进行之前,您需要了解inheritance的这一限制。

  

继承功能的一个严重限制是索引   (包括唯一约束)和外键约束仅适用   单个表,而不是他们的继承子。这是真的   外键约束的引用和引用方。

如果你有幸不使用外键,可以使用是分区。

分区

我不知道您在线阅读的内容,但如果您阅读official documentation,则分区很简单。对于新表来说这是真的。对于旧表来说,它有点棘手。我处理旧表的策略是这样的(它可能不是最好的):

1)创建newtable LIKE oldtable;
2)在newtable上创建分区 3)将数据移动到新表中 4)放下旧桌子并用视图替换它 5)创建触发器以使视图可写(这是非常标准的,您将在文档中找到示例)

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

规格化

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

Double to int

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

手动表拆分

  

我也在想,也许我应该插入我的所有数据   进入临时表,然后在市场收盘后运行一个cron工作   下午4:30,因市场收盘后没有数据插入。

几乎但并不完全。将所有内容插入主表。市场关闭后,使用cron作业将超过30天的数据移动到存档表中。

汇总表

在追踪长期趋势时,您只需要高,低,收盘,开盘,您不需要日内波动。使用此数据创建汇总表(由您的cron填充)并将其用于趋势分析。仅将主表用于日内或短期趋势。