3

我面临着必须向已经有 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 个新列垂直分区到一个新表中,那么每次 iSELECT来自客户:

SELECT ...
FROM Customers

必须将其转换为连接才能获得分区值(即,在我不需要新列的地方永远不会获得性能提升):

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

所以这是对列进行分区的一个缺点。

另一个缺点是我必须同时管理将行插入两个表,而不仅仅是一个。

我能想到的最后一个问题是,SQL Server 现在必须在INNER JOIN我想访问“客户”的任何时候执行。现在和永远都会浪费 CPU 和 I/O 来连接真正是一张表的表 - 除了我决定将它们拆分。

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

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

有哪些优点?

编辑:为什么我还要考虑分区?它主要是空数据,将使表中的列数增加三倍。肯定是坏了!

4

3 回答 3

2

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

但是,有几点:

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

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

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

于 2010-08-17T03:15:51.810 回答
1

如果这些值是 a) 对记录唯一的(给定的客户应该只有一个值,该值将进入 NewColumn1)并且 b) 不被任何其他记录使用(至少,没有其他不需要基本客户的记录信息)我会说把它们放在一张桌子上。只是不要忘记在针对表编写的任何查询中命名您的特定列。

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

于 2010-08-16T19:45:48.920 回答
1

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

  • 首先,请记住,任何表中的给定行都不能超过 8060 字节。因此,如果新列的大小使得理论上可以超过该限制,那么您将在数据库中构建一个定时炸弹。在最不方便的时候,数据插入或更新会引发错误和/或数据会丢失。

    为了防止这种情况,您可能需要使用多个表,这只是大多数 SQL-Server 版本的限制。
    .

  • 另一个重要的考虑因素是数据建模。新列是否与 有一对一的关系 CustomerID?例如,说 eyeColor

    由于列的数量以及您省略了它们的名称这一事实,我怀疑正在考虑非规范化设计。如果新列类似于WebPage1WebPage2WebPage3等,则需要将这些列拆分为单独的规范化表。
    .

但是,如果这些列确实是唯一的项目,彼此无关并且与CustomerID(或该表的主键是什么)具有一对一的关系,并且无法打破大小限制,那么将所有内容放在一个桌子很好。

于 2010-08-17T03:04:06.690 回答