目前我有情况,这让我很害怕。我在数据库中有20k行,这甚至不是数据的1%,我将在未来3个月内拥有。每行代表一个对象(让我们称之为 Object1 )和一些数据。另外,我有每个Object1的stats表,我们称之为Object1Stats,它位于MongoDB中。我每天都有Object1Stats,所以为了获得总统计数据,我应该为Object1的每个Object1Stats求和。
问题是:我经常需要预先计算这些数据。例如,要将其显示给用户,可以按统计信息对Object1集合进行排序。我可以加载它并在代码中排序,但是例如,有5百万个Object1,它会太贵了。
因此,对于每个Object1,我想到每小时预先计算统计数据(Object1Stats每小时更新两次)。但是这个过程让我害怕它需要执行所有操作的时间......我应该拿每个Object1,向MongoDB发送查询以求和Object1Stats,为Object1创建SQL UPDATE。重复此至少 300万次。
我有2个瓶颈:计算MongoDB中的sum(MapReduce)和Postgre中的SQL更新查询。我现在无法真正加速MapReduce(我认为它会很好),但我正在考虑SQL更新。
有任何想法或建议吗?我接受任何建议,甚至建议使用不同的数据库或方法。
,我不能只为对象添加新的统计数据,因为可以经常更改上一天的统计数据,也可以更改前几天的统计数据。
答案 0 :(得分:0)
关于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“river”,这个驱动程序会在MongoDB中发生时将统计信息更改推送到PostgreSQL中。这样你只需为你使用的东西付费,只更新那些在MongoDB中确实发生变化的PostgreSQL对象。负载也会不那么粗糙。 IMO这是首选方式,但我个人不知道创建“河流”驱动程序有多难。
P.S。这是一篇关于使用NOTIFY来更新ES的博文:http://evol-monkey.blogspot.ru/2014/08/postgresql-and-elasticsearch.html