【问题标题】:Should I partition my postgres tables?我应该对我的 postgres 表进行分区吗?
【发布时间】:2016-11-27 13:39:40
【问题描述】:

我将一些股票数据存储在 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 行,但在某些高峰日,它可能会高达 500k 行。这是美国市场开放的 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';

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

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

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

另外,当我在这里时,我应该在我的表上设置索引以使我的上述查询更快吗?

谢谢!

【问题讨论】:

  • 那么提供的慢查询的EXPLAIN ANALYZE 是什么?
  • 先尝试一些不同的索引。多列索引可以很好地工作。在你的情况下,我认为(日期时间,符号)是最有效的,但你也应该尝试相反的方式。我猜你的用例会导致一个表中的数据主要按日期时间字段的顺序排列,我在日期时间上显示一个 BRIN 索引可能非常有效。 postgresql.org/docs/9.5/static/brin-intro.html

标签: database postgresql postgresql-performance


【解决方案1】:

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

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

继承特性的一个严重限制是索引 (包括唯一约束)和外键约束仅适用 到单个表,而不是它们的继承子表。这是真的 外键约束的引用侧和被引用侧。

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

分区

我不知道你在网上读到了什么,但如果你读过official documentation,那么分区就很简单了。好吧,对于新表来说确实如此。对于旧表来说,这有点棘手。我处理旧表的策略是这样的(它可能不是最好的):

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

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

标准化

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

双整数

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

手动分表

我也在想也许我应该插入我所有的数据 进入一个临时表,然后在市场收盘后运行一个 cron 作业 下午 4:30,因为一旦收市,就不会插入任何数据。

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

汇总表

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

【讨论】:

    猜你喜欢
    • 2016-11-26
    • 2016-11-12
    • 1970-01-01
    • 2012-12-30
    • 2011-01-01
    • 2012-09-02
    • 2010-10-25
    • 1970-01-01
    • 2011-01-11
    相关资源
    最近更新 更多