为不同的用户创建多个表是不是更有效?

Posted

技术标签:

【中文标题】为不同的用户创建多个表是不是更有效?【英文标题】:Is it more efficient to create multiple tables for different users?为不同的用户创建多个表是否更有效? 【发布时间】:2020-10-18 17:36:37 【问题描述】:

标题不是很具体,所以我会详细说明。

我正在开发一个数据库系统,在该系统中,用户可以通过简化的 API 将数据添加到 postgres 数据库。

到目前为止,所有用户的数据都被编译到一个表中,结构类似这样:

CREATE TABLE UserData (
    userId int NOT NULL,
    dataId int NOT NULL PRIMARY KEY,
    key varchar(255) NOT NULL,
    data json not NOT NULL,
);

但是,我认为给每个 userId 提供它自己的表可能更有效(并且查询更快):

CREATE TABLE UserData_userId (
    dataId int NOT NULL PRIMARY KEY,
    key varchar(255) NOT NULL,
    data json not NOT NULL,
);
CREATE TABLE UserData_anotherUserId ();
etc...

不过,我担心这会阻塞数据库。

每种方法的优缺点是什么?在什么样的负载/速度要求下都能很好地发挥作用?您认为哪一个更适合高负载、高速的场景?

【问题讨论】:

一般来说,拥有很多“相同”的表是明智的。这是一个维护问题,等等。 @RickJames 我认为您的评论中有错字,您的意思是“这不明智”。 我会保留非分​​区表。除非有非常令人信服的理由,否则我不会以这种方式对数据进行分区。执行这样的分区可能会成为噩梦。编码和调试非常容易出错且成本高昂。 TL/TR:保留您当前的设计 【参考方案1】:

您的建议本质上是partitioning,所以我建议您阅读相关文档。当您的每个操作都覆盖一个分区的大部分时(即选择一个用户的所有数据,或删除一个用户的所有数据),这主要是有利的。

不过,大多数用例最好使用一个正确索引的表。这是一个更简单的结构,并且可以非常高效。如果您的所有查询都是针对单个用户的,那么您将希望所有索引都以 userId 列开头,并且 postgres 将使用它们来有效地仅访问相关行。如果有一天您想要跨多个用户查询数据,那会容易得多。

不过,我建议你不要相信我的话。创建两个结构,生成假数据来填充它们,然后看看它们的行为!

【讨论】:

对。分区不会加速索引扫描,只会对少数分区进行顺序扫描。【参考方案2】:

考虑:

如果每个用户有一个表,您最终可能会得到 x 个表。您预计有多少“用户”? json 数据未绑定,可能会随着您的解决方案/应用程序的增长而增长。您将如何处理缺失的键/值? Users 表将水平增长(更多列),您应该始终致力于垂直增长(更多行)

更好的解决方案是将数据保存在与 user_id 相关的表中。 IE。一个“键”表,其中包含键、添加日期、活动键和外键 (user_id)

这也将解决将您的数据保存为json 的问题,在您的示例中,这将难以维护。而是将该 json 文件打开到一个可以从索引和集群中受益的表中。


如果您在单独的表中将 user_id 引用为外键,则可以在该键上对这些表进行分区或集群,以显着提高速度并补偿增长。这意味着您有一个用于users 的表(id、name、active、created_at、...)和许多链接到该用户的表,例如。 subscriptions (id, user_id, ...), items (id, user_id, ...), things (id,user_id, ...)

【讨论】:

以上是关于为不同的用户创建多个表是不是更有效?的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery:按开始日期和结束日期描述的用户元数据 - 创建跨多个表的排列

SAP query创建

Postgres:为不同角色/用户创建的未来表授予对角色/用户的访问权限

Linux命令大全汇总,让你工作更有效率!

如何创建具有选择的多个用户模型?

SQL Server 2008如何创建分区表,并压缩数据库空间