3

我正在设计一个带有 SQL 后端(Postgresql)的应用程序,我有一些设计问题。简而言之,数据库将用于存储动态发生的网络事件,因此插入速度和性能至关重要,因为“实时”操作取决于这些事件。数据被转储为几个表中的快速默认格式,我目前正在使用 postgresql 触发器将这些数据放入其他一些用于报告的表中。

在典型事件中,数据被插入到两个不同的表中,每个表共享相同的主键(事件 ID)。然后,我需要将数据移动并重新排列到一些不同的表格中,这些表格供基于 Web 的报告界面使用。我的主要目标/关注是保持初始插入表的负载,以便他们可以做他们的事情。报告是次要的,但通过触发器即时发生这种情况仍然很好,而不是我必须查询和管理已经处理的事件的 cron 作业。报告应该/永远不会触及初始插入表。性能明智..这有意义还是我完全离开了?

一旦数据在适当的报告表中,我就不需要在插入表中保留太久的数据,所以我会定期修剪这些数据以提高插入性能。在考虑这种我确信是半常见的场景时,我提出了三个选项:

  1. 使用触发器在初始行插入时触发并填充报告表。这是我最初的计划。

  2. 使用触发器将插入数据复制到临时表(相同格式),然后使用触发器或 cron 填充报告表。这只是一个想法,但我认为对临时表的简单复制操作将卸载上述解决方案中触发器的任何查询。

  3. 修改我的初始输出程序,将所有数据转储到一个表中(而不是跨两个表),然后在该插入上触发以填充报告表。因此,在解决方案 1 是多表到多表触发器的情况下,这将是多表触发器的单表源。

我是不是想太多了?我想把这件事做好。非常感谢任何输入!

4

2 回答 2

3

由于有更多“事情”要做(尽管它们不应该以任何方式影响操作),因此您可能会体验到性能略有提高。但是使用触发器/其他 PL 是一种将其减少到最低限度的好方法,它们的执行速度比从应用程序发送到 DB-Server 的代码更快。

我会接受你的第一个想法1),因为在我看来这是最干净、最有效的方法。 2)是最需要性能的解决方案,因为 cron 将比使用服务器端功能的其他解决方案执行更多查询。3)是可能的,但会导致“丑陋”的数据库布局。

于 2010-09-13T07:53:23.313 回答
0

这是一个旧的,但在这里添加我的答案。

报告是次要的,但通过触发器即时发生这种情况仍然很好,而不是我必须查询和管理已经处理的事件的 cron 作业。报告应该/永远不会触及初始插入表。性能明智..这有意义还是我完全离开了?

恐怕那可能还差得很远,但在少数情况下可能不会。这取决于缓存对报告的影响。请记住,磁盘 I/O 和内存是您的商品,写入者和读取者很少在 PostgreSQL 上相互阻塞(除非他们明确提升锁——例如,SELECT ... FOR UPDATE 将阻塞写入者)。基本上,如果您的表可以舒适地放入 RAM 中,那么您最好从它们中报告,因为您为事件条目的 WAL 段提交保持磁盘 I/O 空闲。如果它们不适合 RAM,那么您可能会遇到报告导致的缓存未命中问题。在这里具体化您的视图(即制作触发器维护的表)可能会减少这些,但它们具有显着的复杂性成本。这个,顺便说一句,如果你选择 1。所以我会暂时把这个记下来作为过早的优化。另外请记住,您可能会在以这种方式具体化视图时引发缓存未命中和锁定争用,因此您可能会在这种方式下引发有关插入的性能问题。

请记住,如果除了 WAL 提交之外,您可以从 RAM 操作,您将不会遇到性能问题。

对于#2。如果您将临时表称为 CREATE TEMPORARY TABLE,那就是要求一团糟,包括性能问题和报告未显示您希望它们显示的内容。不要这样做。如果你这样做,你可能会:

  1. 强制 PostgreSQL 在每次插入时重新计划您的触发器(或每个会话至少一次)。哎哟。
  2. 添加开销创建/删除表
  3. OID 环绕的可能性

ETC.....

简而言之,我认为您想多了。你可以通过在你的 Pg 盒子上增加 RAM 并确保你有足够的内核来处理适当数量的插入会话和报告会话来获得很远的结果。如果您正确规划您的硬件,那么这一切都不是问题。

于 2012-10-03T01:12:26.153 回答