动态创建表来存储用户内容是个好主意吗?

Is it a good idea to create tables dynamically to store user-content?

我目前正在设计一个应用程序,用户可以在其中 create/join 分组,然后 post 分组中的内容。我正在尝试弄清楚如何最好地将此内容存储在 RDBMS 中。

选项 1:为所有用户内容创建一个 table。 table 中的其中一列是 groupID,指定内容 post 编入的组。使用 groupID 创建索引,以便在特定组内快速搜索内容。所有内容reads/writes都会打这首单曲table.

选项 2:每当用户创建新组时,我们都会动态创建一个新的 table。类似于 group_content_{groupName}。所有内容 reads/writes 将被路由到动态创建的特定组 table。

选项 1 的优点:

  1. 跨多个组搜索内容更容易,使用单个简单查询,对单个 table.
  2. 进行操作
  3. 构建简单的交叉 table 查询更容易,因为内容 table 是静态的且定义明确。
  4. 更容易实施架构更改和对 indexing/triggers 等的更改,因为只有一个 table 需要维护。

选项 2 的优点:

  1. 所有读取和写入都将分布在多个 table 中,从而避免了由于大量流量击中单个 table 而可能导致的任何瓶颈(尽管不可否认,所有这些 tables 仍在单个数据库中)
  2. 每个 table 的大小都会小得多,从而允许更快的查找、更快的模式更改、更快的索引等
  3. 如果我们将来想对数据库进行分片,如果所有数据已经​​ "sharded" 跨不同的 table ,那么转换会更容易。

从performance/development/maintenance的角度来看,上述2个选项之间的一般建议是什么?

计算中的主要错误之一是过早优化。这位拥有 20 多年经验的 DBA 认为,您高估了这些组将要发生的 IO。RDBMS 非常擅长在一组标准表中查询和写入此类信息。最坏的情况,您可以稍后对它们进行分区。使用一组表而不是每个用户一组,您将拥有更多的搜索功能和管理便利性。

想象一下架构是否需要更改?你真的想更新成百上千个表或写一些长脚本来解决一个普通的问题吗?坚持使用一组表并忽略分片。相反,想想 "maybe we'll partition the tables someday, if necessary"

这很简单。 (1) 是要走的路。

您将这些列为对第二种方法的优化。所有这些都是错误的观念。请参阅以下评论:

All reads and writes will be distributed across numerous tables, thus avoiding any bottlenecks that can result from a lot of traffic hitting a single table (though admittedly, all these tables are still in a single DB)

读取和写入可以轻松地分布在 table 中。唯一的问题是页面内的写入冲突。这可能是一个很小的考虑因素,除非您每秒处理的事务超过几十个。

由于下一个项目(部分填充的页面),您实际上使用单个 table 和大部分填充的页面会更好。

Each table will be much smaller in size, allowing for faster lookups, faster schema-changes, faster indexing, etc

较小的 tables 可能是性能 灾难 。表存储在数据页上。每个 table 都是一个部分填充的页面。你最终得到的是:

  • 磁盘上有很多浪费 space。
  • 您的页面缓存中有很多浪费 space -- space 可用于存储记录。
  • 在部分填写的页面中浪费了很多 I/O 阅读。

If we want to shard the DB in future, the transition would be easier if all the data is already "sharded" across different tables.

Postgres 支持 table 分区,因此您可以将 table 的不同部分存储在不同的地方。这应该足以满足您分散 I/O 负载的目的。

选项 1:性能=正常开发=容易维护=容易

选项 2:性能=快速开发=复杂维护=困难

我建议选择 Oprion1,对于 BIG table,您可以使用更好的索引或现金索引(对于某些数据库)来管理性能,最后一件事对第二个选项 2 没有任何帮助,因为开发维护时间是致命因素