【问题标题】:Huge amount of updates and postgresql大量更新和 postgresql
【发布时间】:2014-06-19 09:39:52
【问题描述】:

目前我有情况,这让我很害怕。我在数据库中有 20k 行,这甚至不是数据的 1%,我将在接下来的 3 个月内拥有。每行代表一个带有一些数据的对象(我们称之为Object1)。另外,我有每个 Object1 的统计数据表,我们称之为 Object1Stats,它位于 MongoDB 中。我每天都有 Object1Stats,因此要获得总统计数据,我应该对 Object1 的每个 Object1Stats 求和。

问题是:我经常需要预先计算这些数据。例如,将其显示给用户,能够按统计信息对 Object1 集合进行排序。我可以加载它并在代码中进行排序,但是例如使用 500 万个 Object1,它会太昂贵。

所以,我想到了每个 Object1 每小时预先计算统计数据(Object1Stats 每小时更新两次)的想法。但是这个过程让我害怕它需要执行所有操作的时间......我应该获取每个 Object1,向 MongoDB 发送查询以汇总 Object1Stats,为 Object1 进行 SQL UPDATE。重复此操作至少 300 万次。

这里有两个瓶颈:MongoDB 中 sum(MapReduce) 的计算和 Postgre 中的 SQL 更新查询。我现在不能真正加速 MapReduce(我认为它会很好),但我正在考虑 SQL 更新。

有什么想法或建议吗?我接受任何东西,甚至是使用不同数据库或方法的建议。

另外,我不能只为对象添加新的统计数据,因为前一天的统计数据可以经常更改,前几天的统计数据也可以更改。

【问题讨论】:

  • 数据建模中有一条经验法则:“不要存储聚合”。如果您必须存储它们,请确保它们可以增量更新(例如,通过 detail 表上的触发器)

标签: sql mongodb postgresql optimization database


【解决方案1】:

关于 PostgreSQL 端的一些想法:

使用COPY 将新数据加载到临时表中,然后使用单个查询更新对象。它比单独发布每个更新更快。另见this answer。 (如果您的驱动程序允许,那么除了 COPY 和多值插入选项之外,还有 pipeline 选项。

将对象经常更新的部分(统计信息)保存在单独的表格中。

如果您确定所有对象都已更新,那么您可能希望使用COPY 加载更新后的统计数据,然后切换表 (DROP TABLE stats; ALTER TABLE new_stats RENAME TO stats)。

另一方面,如果您正在以明确定义的批次更新统计信息(例如,首先更新对象 1..99999 的统计信息,然后更新对象 100000..199999 的统计信息,依此类推),然后您可以根据这些批次partition 统计表。

另一个角度是使用foreign table wrapper 按需直接从MongoDB 加载统计信息。您可能希望使用存储过程来访问统计信息,该过程将缓存本地表中的统计信息。更新统计信息对于截断缓存至关重要。这种方法的缺点是 PostgreSQL 将为它获取的每个统计信息发出单独的 MongoDB 请求,因此如果您的查询需要触及大量统计信息,那么这种方法可能比每小时批量更新更糟糕。

另一种方法是创建一个 MongoDB“河流”,一个驱动程序,一旦它们在 MongoDB 中发生,就会将统计更改推送到 PostgreSQL。这样,您只需为使用的内容付费,仅更新那些在 MongoDB 中确实发生更改的 PostgreSQL 对象。负载也将不那么粗糙。 IMO这是首选方式,但我个人不知道创建“河流”驱动程序有多难。

附:这是一篇关于使用 NOTIFY 更新 ES 的博文:http://evol-monkey.blogspot.ru/2014/08/postgresql-and-elasticsearch.html

【讨论】:

    猜你喜欢
    • 2021-03-18
    • 2019-08-20
    • 1970-01-01
    • 2011-03-07
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 2021-08-01
    • 1970-01-01
    相关资源
    最近更新 更多