【问题标题】:Horizontal/Vertical partitioning and relations水平/垂直分区和关系
【发布时间】:2014-11-07 11:52:17
【问题描述】:

我有一个关于关系数据库中水平/垂直分区的问题。

我会用一个例子来演示:

假设我们有一个不相交的 Person 继承。一个人可以注册或未注册,但不能同时注册。

一个人与表House也是多对​​多关系,一个房子可以被1..*个人拥有,一个人可以拥有1..*个房子。

如果我当时对 Person 表进行水平分区,这意味着我们有两个相同的表,但一个包含已注册的人员,一个包含未注册的人员。它如何处理多对多关系?

我也想过对关系进行分区,但是如果person和其他表之间有n个关系,水平分区会导致表增长n * 2。这真的是要走的路吗?

我希望我表达清楚并提前感谢。

【问题讨论】:

    标签: sql database relational-database partitioning


    【解决方案1】:

    没有“正确的方法”可以做到这一点。有不同的权衡取舍的不同方法。但是,我会从这样的事情开始:

                   +------+          +-----+
                   |Person<----------+House|
                   +^----^+          +-----+
                    |    |                  
                    |    |                  
    +---------------++  ++-----------------+
    |RegisteredPerson|  |UnRegisteredPerson|
    +----------------+  +------------------+
    

    Person 会有一个自动生成的 PersonID。子表 RegisteredPerson 和 UnregisteredPerson 将具有相同的主键(使关系 1 到 0 或 1)。 使用这种方法来强制一个只有一个 RegisteredPerson 或 UnRegistered 人的 Person 有点棘手。最直接的方法是只允许通过维护正确不变量的存储过程对表进行写访问。还有一些方案使用触发器并使用子类型标记 Person 记录。

    【讨论】:

      【解决方案2】:

      关于术语的说明:在数据库的上下文中,“水平”和“垂直”分区通常是指与您的问题完全无关的存储机制。这是一个关于继承的问题。

      就目前而言,劳伦斯的回答是正确的。正如您所描述的问题,您需要一个名为 Person 的实体来与 House 建立关系。执行“唯一一个”注册的两种方法是将 id 存储在 Person 表中。一种方法是:

      create table Person (
          . . .
          RegisteredId int references RegisteredPersons(RegisteredPersonId),
          UnregisteredId int references UnregisteredPersons(UnregisteredPersonId),
          check (RegisteredId is null or (UnregisteredId is null)
      )
      

      (请注意,这允许一个人既不能注册也不能取消注册,尽管check 可以固定。)

      另一种选择是:

      create table Person (
          . . .
          RegType varchar(255),
          RegId int
          check RegType in ('Registered', 'Unregistered')
      )
      

      然后,根据数据库,您可以定义定义外键引用的计算列或视图。像这样的:

          RegisteredId as (case when RegType = 'Registered' then RegId end),
          UnregisteredId as (case when RegType = 'Unregistered' then RegId end),
      

      优点和缺点。第一种方法强制执行外键关系。但是,它会为每种类型占用一个整数的存储空间。对于两种类型,这没什么大不了的。

      第二种方法需要跨数据库的非标准功能。例如,在 SQL Server 和 Oracle 中,您可以强制执行外键关系——但一种是使用计算列执行此操作,另一种是使用过滤索引执行此操作。

      【讨论】:

      • 感谢您提供有关不相交继承的内容丰富的帖子。但是,我真正要问的是如何使用关系对表进行分区。
      • @LinusEsbjörnsson 。 . .水平分区根据键列中的值将表的行分散到单独的存储空间中。我不清楚这与您的问题有何关系。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-23
      • 2015-09-24
      • 2013-12-10
      • 1970-01-01
      • 2014-02-16
      • 1970-01-01
      • 2012-04-02
      相关资源
      最近更新 更多