代码之家  ›  专栏  ›  技术社区  ›  Ian Boyd

SQL Server:当我总是要重新加入垂直分区时,在垂直分区中有任何值吗?

  •  2
  • Ian Boyd  · 技术社区  · 14 年前

    我面临着必须向已经有32列的表中添加64个新列的问题。举例来说:

    Customers
    (
        CustomerID int
        Name        varchar(50)
        Address     varchar(50)
        City        varchar(50)
        Region      varchar(50)
        PostalCode  varchar(50)
        Country     varchar(2)
        Telephone   varchar(20)
    
        ...
        NewColumn1  int null
        NewColumn2  uniqueidentifier null
        NewColumn3  varchar(50)
        NewColumn4  varchar(50)
        ...
        NewColumn64 datetime null
    
        ...
        CreatedDate datetime
        LastModifiedDate datetime
        LastModifiedWorkstation varchar(50)
        LastModifiedUser varchar(50)
    )
    

    大多数情况下,这些新列将包含 null .

    它也是一个给定的 如果 我将这64个新列垂直分区到一个新表中,然后每次 SELECT 来自客户:

    SELECT ...
    FROM Customers
    

    必须转换为联接才能获得分区值(即 从未 在不需要新列的情况下,将获得性能提升):

    SELECT ...
    FROM Customers
        INNER JOIN Customers_ExtraColumns
        ON Customers.CustomerID = Customers_ExtraColumns.CustomerID
    

    那就是一个 反对的论点 对列进行分区。

    其他的 反对的论点 我必须同时在两个表中插入行,而不仅仅是一个表。

    决赛 反对的论点 我能想到的是,SQL Server现在必须执行 INNER JOIN 我想随时访问“ 客户 “。现在和永远都会浪费CPU和I/O来连接真正是一个表的表——除了我决定将它们分开。

    所以我的问题是:我为什么要把它们分开?

    当64列大部分为空时,将它们垂直分区到单独的表中是否有任何值?空占用很少的空间…

    专业人士是什么?

    编辑: 为什么我还要考虑分区?它主要是空数据,这将使表中的列数增加三倍。 当然 一定很糟糕!

    3 回复  |  直到 14 年前
        1
  •  2
  •   Cade Roux    14 年前

    为了简化数据模型,如果没有进一步的信息,我可能不会进行分区,但您还没有在这些新列中指出数据的性质(可能有些列是应该规范化的数组)。

    但是,有些要点:

    如果您进行垂直分区,并且在补充表上有FK约束,这可能有助于在某些情况下消除联接,因为它知道只有一行存在。显然,它将在相同的唯一键上建立索引,这将有助于消除确定是否存在交叉联接的需要,因为只能有0或1行。

    您可以有一个可更新的视图,它联接两个表,并在视图上有一个触发器,该触发器插入到两个联接的表中以生成视图。您还可以决定执行左联接,并且只在需要它的任何列非空时创建一个补充行。

    您还可以使用一组稀疏连接的补充数据表。显然,这也需要连接,但是您也可以像使用1一样,对多个补充表使用类似的技术。

        2
  •  1
  •   AllenG    14 年前

    如果这些值是a)一个记录的唯一值(一个给定的客户应该只有一个新列中的值1)和b)没有被任何其他记录使用(至少,没有其他记录不需要基本客户信息),我会说将它们保留为一个表。不要忘记在针对表编写的任何查询中命名特定的列。

    我来自一个EDI背景,有时您必须处理每行包含30+列数据的平面文件。正如你所说的, NULL 占用的空间不多,如果你 从未 将独立地抓取列(并且您将永远无法独立地获取基本客户数据),我会说您做得对。

        3
  •  1
  •   Brock Adams    14 年前

    答案是从问题中省略的细节。列的数量无关紧要,重要的是数据的性质。

    • 首先,记住 a given row in any table can never exceed 8060 bytes . 所以如果新列是 其大小应使该限制能够 理论上,你会超过 在 数据库。在最不重要的时候 方便,数据插入或更新 将引发错误和/或数据将 迷路了。

      为了防止这种情况,你可能需要 要使用多张桌子,只需 大多数版本的限制 SQLServer。
      .

    • 另一个重要考虑是 数据建模。执行新列 与…有一对一的关系 CustomerID ?例如,假设 eyeColor ?

      因为列的数量和 你忽略了他们 名字,我怀疑 非标准化设计正在 仔细考虑。如果新列是 类似的东西 WebPage1 , WebPage2 , WebPage3 等等,然后 这些需要分成 分开的, normalized 表。
      .

    但是,如果列确实是唯一的项,彼此不相关,并且与 客户编号 (或者不管该表的主键是什么),并且不能突破大小限制,那么将所有内容都放在一张表中是完全正确的。

    推荐文章