一张大桌子 vs 几张小桌子

mba*_*jur 5 postgresql database-design physical-design

请注意,下面的示例只是一个示例,我的场景要复杂得多,而且我尝试对其进行建模的方式确实很有意义

假设我正在我的一个应用程序中为审计事件创建一个表 - 所以所有的“event_created”、“user_created”等等。该表包含几列,其中一些是其他表的外键。随着时间的推移,这个单个表可以增长到数百万条记录。

从性能的角度来看,对所有这些事件使用单个表还是对每种事件使用单独的表并在单独的表上操作是更快、更高效?还是差别不大?为每种事件创建一个单独的表可能听起来很愚蠢,但您需要相信我,在我的现实世界场景中,这真的很有意义。

Bas*_*que 12

非规范化仅作为最后的手段

不要为想象中的性能问题非规范化你的表设计。避免陷入过早的优化

设计一个合适的结构。生成虚假数据以填充表。在类似于您的部署方案的情况下运行测试。如果证明存在严重的性能问题:

  • 使用 EXPLAIN & ANALYZE 功能研究问题的性质。
    • 检查索引的使用。验证查询中是否按预期使用了现有索引;如果没有,请使用不同的方法重新编写查询。在需要的地方添加索引。
  • 研究如何调整 Postgres。
  • 通过使用PL/pgSQL等语言编写函数,尝试将一些逻辑从您的应用程序移至数据库服务器,其中所有数据都位于执行代码的本地。
  • 在您的RAID设备上安装更大的缓存单元。根据您的情况,考虑调整缓存以分配更多的读取和写入;他们通常默认为 50-50。
    (顺便说一句,请确保您的 RAID 的写缓存由电池供电,以避免破坏您的数据库或其他文件。)
    • 或者,如果使用ZFS而不是 RAID,学习调整它以在更快的驱动器上优先考虑您的数据库。
  • 考虑使用分区来物理隔离存储中的行。考虑添加更快的存储,例如存储最常访问数据的企业级固态存储,或存储您最想快速访问的数据,例如Big Cheese使用的数据。
    • 分区伴随着限制和权衡。所以请确保您没有更好的方法来解决您的性能问题。
    • 如果您确实使用分区,请注意最近版本的 Postgres(我依稀记得是 10、11、12)已经通过声明式分区的改进得到了显着改进。
  • 聘请 Postgres 专家为您的测试和调整提供咨询。

只有在用尽所有途径来修复已证明的性能问题之后,您才应该考虑非规范化。

Postgres 是一个强大的企业级数据库系统。具有足够 RAM 和明智索引的现代硬件上的几百万行应该完全没有问题。

另一方面,如果不同类型的事件代表不同的实体,则应将它们保存在单独的表中。我们如何知道相似类型的行是否是不同的实体?可以从以下问题中找到线索:它们是否具有大多数具有相同语义的相同列?您的用户是否曾经想一起显示或报告?您是否想将(计算计数、平均值、中位数等)聚合在一起?

请注意,作为一个历史悠久的产品,可以追溯到计算机硬件在功能和配置方面比今天的硬件更加有限的时代,默认情况下 Postgres在初始安装时具有相当保守的设置。例如,默认情况下 Postgres 运行在较旧的Raspberry Pi 上!因此,任何在功能更强大的硬件上运行更大数据库的人都应该进行一些调整。