假设我已经在现场产品中使用此表很多年了:
[UserContactInfo]
[UserContactInfoId] uniqueidentifier not null
[UserId] uniqueidentifier not null PK to [User] table
[FirstName] varchar(50) null
[LastName] varchar(50) null
[Street] varchar(200) null
[City] varchar(50) null
[State] varchar(2) null
[Zip] varchar(10) null
many other fields
当前最大行字节总数目前仅为1K-远远小于每行8K的限制。
当前大约有1000万行或9GB。
让我们说,由于表规模大,在事务中运行所有操作的必要性以及广泛的数据库维护窗口的负面影响,数据迁移非常痛苦。
现在我要添加邮件地址。
选项1:我可以添加其他列:
[MailingStreet] varchar(200) null
[MailingCity] varchar(50) null
[MailingState] varchar(2) null
[MailingZip] varchar(10) null
选项2:我可以输入地址:
[AddressType] byte not null
对应于在写入时强制执行的C#枚举
enum AddressType {
Physical=1,
Mailing=2}
,并且在数据库维护作业期间运行脚本以将所有现有行更新为[AddressType] = 1
我的问题是哪个选项的效果更好?
选项1的底片:
(a)最初,所有行将有4个未使用的列,并且即使多年后,很可能仍将是具有实际数据的行的低百分比。但是我相信SQL Server只需要一点即可记录col为空。 (b)它将行稍微移近8K边界(尽管距离还很远) (c)如果我们需要其他地址类型,则意味着更多的列名
选项2底片:
(a)将来某个时候该表可能有两倍的行。我可以在[UserId],[AddressType]
上添加复合索引,并且我确定SQL Server有各种技巧可以优化性能,但是我怀疑它是否会达到一半大小的表的性能?
有人对选项1与选项2的取舍有更好的了解吗?
答案 0 :(得分:0)
选项2是更标准的方法。这意味着您不必复制列定义(考虑如果您决定将城市扩展到60个字符,会发生什么情况),并且更适合以后添加(更多地址类型)。
它还为您提供了更大的查询灵活性。如果您有任何查询出于查询目的将所有地址都视为“相等”(使用该地址无关紧要),那么编写起来就很简单,并且如果您需要限制为特定的地址类型,则可以可以在WHERE
子句中应用简单的过滤器。
与方法1相比-如果您要均等地查询所有地址,则需要在WHERE
子句中分别命名所有地址列,并且需要格外小心,以免混淆各个元素(例如,为了找到Tampa, CO
的所有用途,您需要确保不要将邮寄地址中的城市与实际地址的状态混为一谈。而且,如果您希望允许人们过滤到各个地址类型,则必须进行翻译,例如将UI选择成单独的列名,通常会导致需要动态SQL。
(根据用例的不同,您可能需要分别决定姓和名以及它们是否与地址或用户相关联,以决定它们是否仍属于该表,因为它已经建模了多个地址)