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

标签 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'

平均每天我会插入 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';

我真的不想每天检查一个表是否存在 25 万到 50 万次,所以我想我可以运行一个 cron 作业来每月创建一个表,而不用去检查?

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

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

此外,当我在这里时,有什么关于我应该在我的表上使用索引的建议,以使我的上述查询速度更快吗?

谢谢!

最佳答案

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

PostgreSQL partitioning建立在表继承之上。在继续之前,您需要了解 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.

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

分区

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

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

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

规范化

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

double 整数

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

手动分表

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.

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

汇总表

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

关于database - 我应该对我的 postgres 表进行分区吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38546975/

相关文章:

performance - EC2/EBS 上的 PostgreSQL 性能

sql - PostgreSQL:以主键作为排序键的 ORDER BY 非常慢

postgresql - 为什么我为同一个查询获得不同的查询计划(在主服务器/复制服务器上)

php - 根除电子邮件地址的模式

database - 连接和语句池有什么好处?

postgresql - 在 postgresql 中,为什么 _PG_init 被调用两次?

postgresql - pg_ctl : error while loading shared libraries: libpq. so.5

sql - 为什么以下连接会显着增加查询时间?

mysql - 当更新表有一个字段然后第一个时更新两个表

Mysql 8自定义字符串函数总是返回零