为不同的用户创建多个表是不是更有效?
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:按开始日期和结束日期描述的用户元数据 - 创建跨多个表的排列