为什么我会在这个世界上建立很多关系呢?

时间:2015-10-21 22:20:49

标签: ruby postgresql activerecord multidimensional-array has-many

我刚刚遇到关于关系和数据库的有趣情况。我正在编写一个ruby应用程序,对于我的数据库,我正在使用postgresql。我有一个父对象" user"和相关的对象" thingies"用户可以拥有一件或多件东西的地方。使用单独的表与仅在父表中的字段中嵌入数据有什么好处?

来自ActiveRecord的示例:

使用相关表格:

def change
    create_table :users do |i|
        i.text :name
    end
    create_table :thingies do |i|
        i.integer :thingie
        i.text :discription
    end
end
class User < ActiveRecord::Base
    has_many :thingies
end
class Thingie < ActiveRecord::Base
    belongs_to :user
end

使用嵌入式数据结构(多维数组)方法:

def change
    create_table :users do |i|
        i.text :name
        i.text :thingies, array: true # example contents: [[thingie,discription],[thingie,discription]]
    end
end
class User < ActiveRecord::Base
end

相关信息

我使用heroku和heroku-posgres作为我的数据库。我正在使用他们的免费选项,这限制了我10,000行。这似乎让我想要使用多维数组方式,但我真的不知道。

4 个答案:

答案 0 :(得分:11)

在字段中嵌入数据结构可以用于简单的情况,但它会阻止您利用关系数据库。关系数据库旨在查找,更新,删除和保护您的数据。如果嵌入字段包含自己的wad-o-data(数组,JSON,xml等),那么您最终会编写所有代码来自己完成。

有些情况下嵌入字段可能更合适,但对于这个问题,我将使用一个案例突出显示相关表approch的优点。

想象一下博客的用户和帖子示例。

对于嵌入式post解决方案,你会得到一个像这样的表(psuedocode - 这些可能是无效的ddl):

create table Users {
id int auto_increment,
name varchar(200)
post text[][],
}

使用相关表格,您可以执行类似

的操作
create table Users {
id int auto_increment,
name varchar(200)
}
create table Posts {
id auto_increment,
user_id int,
content text
}

对象关系映射(ORM)工具:使用嵌入式帖子,您将手动编写代码以向用户添加帖子,浏览现有帖子,验证它们,删除它们等。在单独的表设计中,您可以利用ActiveRecord(或您正在使用的任何对象关系系统)工具来保持代码更加简单。

灵活性:想象一下,您想在帖子中添加日期字段。你可以使用嵌入式字段来完成它,但是你必须编写代码来解析你的数组,验证字段,更新现有的嵌入式帖子等。使用单独的表格,这会更简单。此外,假设您要为批准所有帖子的系统添加编辑器。通过关系示例,这很容易。以查找由Bob&#39; Bob编辑的所有帖子为例。使用ActiveRecord,您只需要:

Editor.where(name: 'Bob').posts

对于嵌入式方面,您必须编写代码来遍历数据库中的每个用户,解析他们的每个帖子并查找“Bob&#39;在编辑器领域。

效果:想象一下,您有10,000名用户,平均每人有100个帖子。现在,您要查找在特定日期完成的所有帖子。使用嵌入字段,您必须循环遍历每条记录,解析所有帖子的整个数组,提取日期并再次检查您想要的日期。这将咀嚼cpu和磁盘i / 0。对于数据库,您可以轻松索引日期字段并提取所需的确切记录,而无需解析每个用户的每个帖子。

标准:使用特定于供应商的数据结构意味着将应用程序移动到另一个数据库可能会很麻烦。 Postgres似乎有一组丰富的数据类型,但它们与MySQL,Oracle,SQL Server等不同。如果您坚持使用标准数据类型,您将更容易交换后端。

这些是我从顶部看到的主要问题。我犯了这个错误并付出了代价,所以除非有超级令人信服的理由,否则我会使用单独的表格。

答案 1 :(得分:2)

如果用户John和Ann有相同的东西怎么办?记录将被复制,如果您决定更改thingie的名称,则必须更改两个或更多记录。如果thingie存储在单独的表中,则只需更改一条记录。仅供参考https://en.wikipedia.org/wiki/Database_normalization

答案 2 :(得分:2)

一对多的好处:

  1. 更简单的ORM(对象关系映射)集成。您可以使用它,但您必须使用本机sql定义表。拥有不同的表更容易,您可以使用自动生成的映射。
  2. 如果2个或更多人可以拥有相同的东西,那么10,000行的空间限制将与一对多的关系更进一步。&#34;
  3. 分别处理用户和物品。在某些情况下,您可能只关心人或物,而不是他们彼此的关系。一些示例,更新用户名或东西描述,获取所有东西(或所有用户)的列表。从单个表中进行选择可能会使其难以使用。
  4. 维护和操作更容易。在更新用户或东西(名称更改,电子邮件地址更新等)的情况下,您只需要在其表中更新1条记录,而不是编写更新语句&#34;其中user_id =?&#34;。
  5. 可执行的数据库约束。如果一个东西不是由任何人拥有怎么办?用户列现在是否可以为空?它必须在单个表格的情况下,所以你不能强制执行一个简单的&#34;而不是nillable&#34;用户名,例如。
  6. 当然有很多原因。如果您使用的是关系数据库,则应将对象(用户和东西)分离为单独的表来使用一对多。考虑到您对记录数量的限制以及数据集的大小很小(低于10,000),您不应该感觉到标准化数据的不足。

    短暂的事实是两者都有好处。例如,您可以通过单表方法获得更快的读取时间,因为您不需要复杂的连接。

    这是一个很好的参考,两者的优点/缺点(规范化是多表方法,非规范化是单表方法)。 http://www.ovaistariq.net/199/databases-normalization-or-denormalization-which-is-the-better-technique/

答案 3 :(得分:1)

除了其他提到的好处之外,还有一个关于标准的事情。如果你单独使用这个应用程序,那么这不是问题,但如果其他人想要改变某些东西,那么噩梦就会开始。 这个家伙可能需要花很多时间才能理解它是如何独立运作的。修改这样的东西会花费更多的时间。这样,一些简单的改进可能非常耗时。在某些时候,你将与其他人合作。因此,总是像代码最终使用代码的人一样,是知道你住在哪里的野蛮的精神病患者。