如何处理可变列的表设计


17

我有一个表设计方案,作为非DBA类型,我想就哪种方案更具可扩展性提出意见。

假设您被要求在都市圈的房屋上记录信息,从一个小社区(200座房屋)开始,但最终增长到5000000多个房屋。

您需要存储以下基本信息:ID#(可以用作唯一索引的唯一批号),Addr,City,State,Zip。很好,简单的表可以处理它。

但是每年,都将要求您记录有关所有房屋的额外信息-信息将每年更改。因此,例如,在第一年,要求您记录所有者的姓氏和平方英尺。第二年,要求您保留姓氏,但丢弃平方英尺,而是开始收集所有者的名字。

最后-每年,额外列的数量都会改变。可能从2个额外的列开始,然后在明年移至6,然后回落至2。

因此,一种表方法是尝试将自定义信息添加为房屋表中的列,因此只有一个表。

但是我有一种情况,有人为此安排了桌子:

“房屋表”列:ID,地址,城市,州,邮政编码-每个房屋只有一行

ID   Addr              City     State  Zip 
-------------------------------------------
1    10 Maple Street   Boston      MA  11203

2    144 South Street  Chelmsford  MA  11304

3    1 Main Avenue     Lowell      MA  11280

“自定义信息表”列:ID,名称,值-表如下所示:

ID   Name             Value

1    Last Name        Smith

2    Last Name        Harrison

3    Last Name        Markey

1    Square Footage   1200

2    Square Footage   1930

3    Square Footage 

因此,每个房屋记录都有多个行。每年,当可选信息需要更改时,该表实际上都会被重建,因此明年它可能看起来像:

1    Last Name    Smith

2    Last Name    Harrison

3    Last Name    Markey

1    First Name   John

2    First Name   Harry

3    First Name   Jim

最终,您积累了100,000个房屋行,并且一年中有10条额外的信息;第二个表现在是1,000,000行信息​​,其中许多具有冗余(描述)信息。总体而言,数据库要求是人们每天需要获取房屋行信息+相关的自定义字段值数千次。

所以我的问题是:改为以下做法是否不好(或可怕):

A)布置房屋表,并猜测最大数量的自定义列(可能称为“ 1”至“ 10”),然后将这些自定义值插入房屋行中

要么

B)将自定义信息存储在房屋表中,但是每年当需求发生变化时,仅使用自定义信息所需的列数来重建房屋表,这样的想法可能会变得毫无用处,并且您永远都不知道最大数量可能会要求提供可选字段?

谢谢,希望这有意义!


嗨,您是如何处理问题的?我在相同的场景中运行,我将为每个额外的信息创建一个关系表,并将其与视图一起呈现为“单个表”。
Benj

Answers:


15

您几乎有4个选择:

NoSQL的 - 定义每一个记录被存储为一组键/值对。这是非常灵活和快速的。并非所有的报表编写者都支持这种存储方式。NoSQL有许多示例数据库实现。目前似乎最流行的一个是MongoDB。

EAV - 定义这是打开或者整个表或在其侧面上的部分(在另一个表)。如果您已经拥有一个内部关系数据库,而您又不能轻易离开它,那么这是一个不错的选择。您提供的自定义信息表示例是一个EAV表的很好的示例。

带有XML列的标准表 -认为这是NoSQL满足关系表的原因。XML列中存储的数据可以是XML支持的任何格式,包括多个相关的子数据。对于您知道将成为“常规”列的列,可以将它们构建为适当的列类型以存储数据(姓,地址,城市,州等)。

具有大量额外列的标准表 -您有一个关系数据库,不能使用XML或EAV,并且NoSQL不是一个选择。每种类型添加许多额外的列。我猜想30个或更多的varchar,30个或更多的整数,15个或更多的数字。并且,一旦将一列用作值,就不要重复使用它。并且也不要删除该列

在所有这些解决方案中,我个人认为您将发现NoSQL或EAV方法是最成功的,而重构代码和架构的次数最少。

您将遇到这样的情况:一年而不是第二年收集数据,然后再收集一次。试图用正确的信息更新较旧的数据是有问题且昂贵的。存储都不是。


我听说您也可以使用数据透视表或类似的东西
Alexander Mills

2

要回答关于这两个选项的问题,我都认为这两个都不对。A)将您锁定,B)的工作量很大。您描述的当前架构还不错(除了将信息名称(“名字”,“平方英尺”等)作为字符串而不是引用查找表的ID之外,还不错。

但是,在我看来,这似乎是NoSQL数据库(http://en.wikipedia.org/wiki/NoSQL)的不错选择。尽管我从未使用过这种数据库,但是您所描述的是可以解决的典型情况。


0

如果自定义列的并发数是有限的并且已知限制(例如,字符串的不超过10-20个自定义列,整数则不超过x列等)。
您可以将基表与每个数据类型一起使用额外的字段,而改为每年重建表的过程都会创建该年的视图,其中仅包含相关的自定义列,并重命名通用字段以反映该年的内容。

House Table:
ID, Addr, City, State, Zip, custom_string1,cs_2,cs_3,custom_integer_1,ci_2,ci_3 ...

create view house_2014 as 
select ID, Addr, City, State, Zip,
custom_string1 as last_name,cs_2 as first_name ...

这种方法的问题是,您没有历史记录,但是可以在更改列要求之前每年轻松地进行复制。

create table house_2014_archive as select * from house_2014;
drop house_2014;
create view house_2015 as "select column list for new year";

0

您可以列举所有要存储此数据的方案吗?

如果可以将有限数量的列组合应用于表,则尝试使用通用列建模“基本表”,这些通用列将应用于所有方案,然后创建更多表(以实现某种继承;在ERD和数据库设计中称为子类型/超类型。)

每个场景只有一张桌子,这样至少您可以保持桌子整洁,并且可以避免将街道地址存储在“姓氏”列中...

看看这个设计问题:https : //stackoverflow.com/questions/554522/something-like-inheritance-in-database-design

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.