仅适用于一小部分记录的数据存储设计

Jas*_*son 5 sql-server-2008 database-design

所以我的老板和我在如何最好地设计我们的数据库以存储某些客户的杂项数据存在分歧。

基本上,我们有一堆类似于此格式的表格(为简单起见,使用伪代码):

TABLE [dbo].[SalesData]
[CampaignID] int IDENTITY(1, 1) NOT NULL, (This is the PK)
[CustomerID] int NULL,
[Calls] float NULL,
[Responses] float NULL,
[Sales] float NULL,
[Revenue] money NULL,
[Cost] money NULL,
[WebSales] float NULL,
[Channel] nvarchar(20) NULL
Run Code Online (Sandbox Code Playgroud)

发生的情况是,随着我们获得客户,我们有时被迫为每个客户添加某种自定义数据收集。对于此表,除了 WebSales 和 Channel 仅用于 1 个客户端之外,每个客户端都使用所有内容(我们有大约 20 个)。另一个客户想要跟踪几条新数据,因此,我们要么需要添加更多列,要么将这些数据分拆到相关表中并启动超类型-子类型系统。

我想做的也是剥离 WebSales 和 Channel,并以这种方式为每个客户添加一个表:

TABLE [dbo].[SalesData_Client1] 
[CampaignID] int NOT NULL, (PK and FK to the SalesData table)
[WebSales] float NOT NULL DEFAULT 0,
[Channel] nvarchar(20) NOT NULL DEFAULT ''
ADD CONSTRAINT [CK__SalesData_Client1__CustomersCampaignID] 
CHECK (dbo.CustomerOfCampaignID(CampaignID) = Client1) 
Run Code Online (Sandbox Code Playgroud)

然后我会从原始表中删除这些列,并使第二个客户端也成为这样的表。老板认为这意味着随着我们获得客户,我们将不得不添加太多表,并希望添加更多列。他宁愿像这样更改 SalesData 表:

TABLE [dbo].[SalesData]
[CampaignID] int IDENTITY(1, 1) NOT NULL, (This is the PK)
[CustomerID] int NULL,
[Calls] float NULL,
[Responses] float NULL,
[Sales] float NULL,
[Revenue] money NULL,
[Cost] money NULL,
[Unknown] char(10) NULL,
[Misc1] float NULL,
[Misc2] nvarchar(20) NULL
[Misc3] int NULL,
[Misc4] int NULL
[Misc5] int NULL
Run Code Online (Sandbox Code Playgroud)

“杂项”列可以用于任何用途,然后程序员可以“根据客户端来解决”。我知道为什么你不应该这样做的原因,它违反了规范化,并且会随着我们添加列等而使性能越来越差。每个新客户可能意味着另一个新表。他还指出,像 Websales 这样的新列最终可能会被 1 个以上的客户使用,如果我们应该将它放在多个子类型表中,或者将它从多个子类型表移动到主表,那将是一个巨大的痛苦曾经想这样做。

有没有比我想出的超类型/子类型解决方案更好的方法可以让他和程序员更轻松?一个重要的注意事项是每个客户的数据基本上都在它自己的宇宙中,永远不会混合。我意识到这有点主观,答案将取决于我们认真期待的“杂项”列的数量。我想走子类型路线的原因是因为我知道下一个客户端可能需要 5 个新的 bigint 列。

Fru*_*ner 3

为了真正灵活,您可以采用“实体-属性-值”路线,但这可能有点过头了,而且很多人认为 EAV 是一种可怕的反模式。

如果您认为最终会在一个表中得到数十个特定于客户的列,我认为特定于客户的表可能是更好的方法。