我们已经成功地设计了用于存储通信的PostgreSQL数据库结构,一年过去了,用户正在积极地填充它,现在它已拥有
数百万条记录 ,并且...事情开始放缓。

事实是,
随着表容量的增加,索引的“深度”也增加了 -尽管是对数的。 但是随着时间的流逝,这迫使服务器要
处理许多页面的数据以执行与开始时相同的读/写任务。
这就是
分区的解救之道。
我注意到,这与分片无关,即与不同数据库或服务器之间的数据分配无关。 因为即使将数据分成
多个服务器,也无法摆脱索引随时间“膨胀”的问题。 显然,如果您有能力每天调试一台新服务器,那么您的问题将不再只是特定数据库的问题。
我们将不考虑用于“在硬件中”实现分区的特定脚本,而是考虑方法本身-什么以及如何“切成片”,以及这种愿望会导致什么。
概念图
再次,我们定义我们的目标:我们要确保今天,明天和一年后,在任何读/写操作期间读取的PostgreSQL数据的数量保持大致相同。
对于任何
按时间顺序累积的数据 (消息,文档,日志,档案等),作为分区键的自然选择是
事件的
日期/时间 。 在我们的例子中,这种事件是
消息发送的
时刻 。
请注意,用户几乎总是
只使用“最新”此类数据-他们阅读最新消息,分析最新日志……不,当然,他们可以在时间上往回滚动,很少这样做。
从这些限制中,很明显,
“每日”部分将是消息的最佳解决方案-毕竟,我们的用户几乎总是会“今天”或“昨天”阅读收到的消息。
如果我们白天几乎只写和读一个节,这将使我们
更加有效地使用内存和磁盘 -因为与整个表的“大而粗”节不同,所有节索引都容易装入RAM。
循序渐进
总的来说,以上所有听起来都是一笔可观的利润。 这是可以实现的,但是为此,我们将不得不努力-因为对
一个实体进行分区的
决定导致需要“切割”并与其关联 。
消息,其属性和预测
由于我们决定按日期剪切消息,因此根据实体的属性划分实体属性(附件文件,邮件列表)以及消息的日期也是合理的。
由于我们的典型任务之一是仅查看消息寄存器(未读,传入,全部),因此按消息日期将它们“吸引”到分区中也是合乎逻辑的。

将分区键(消息的日期)添加到所有表:收件人,文件,注册表。 您不能添加到消息本身,而是使用现有的DateTime。
主题
由于主题是多条消息,因此不可能在同一模型中“剪切”,因此必须依靠其他内容。 在我们的情况下,
对应的第一个消息的
日期是理想的-即主题本身创建的时刻。

将分区键(主题日期)添加到所有表:主题,参与者。
但是现在我们同时遇到两个问题:
- 在哪个部分搜索有关该主题的帖子?
- 在哪个部分中从消息中搜索主题?
您当然可以继续在所有部分中进行搜索,但这将非常可悲,并且会否定我们所有的收入。 因此,为了知道确切的位置,我们将逻辑链接/指向各节:
- 在消息中,添加带有主题日期的字段
- 为此主题添加一组消息日期 (您可以使用单独的表,也可以使用日期数组)

由于对每个单独信件的消息日期列表几乎没有修改(毕竟,几乎所有消息都在相邻的1-2天之内),因此我将继续介绍该选项。
总计,考虑到分区,我们的基础结构采用以下形式:
表:RU,如果您不喜欢西里尔字母,则最好不要查看表/字段的名称 节省一分钱
好吧,如果我们不是使用基于字段值分布的
经典分区选项 (通过触发器和继承或PARTITION BY),而是在应用程序级别上``手动''使用,我们可以看到分区键的值已经存储在表本身的名称中。
因此,如果您非常
担心存储的数据量 ,则可以摆脱这些“额外”字段并参考特定表。 的确,在这种情况下,来自多个部分的所有样本都必须提交给应用程序侧。