具有不同字段集的记录的数据库设计

时间:2012-11-02 07:52:56

标签: php mysql database-design application-design

问题

1)我正在寻找一种合适的方法来设计一个Web应用程序,特别是数据库模式,这样我就可以拥有一个基表,其中包含给定的所有核心字段服务,然后根据服务类型,我需要一组额外的字段与服务相关联。

我需要以这样的方式执行此操作,即执行搜索将是直接的并提供合理的性能。我可能会查看某种类型的全文搜索,但最多只能有5个并发用户。

我的应用程序的最终目标是能够在整个数据库中搜索任何给定的关键字并返回所有相关记录。我最初希望将每种服务类型的设置字段拆分为具有各自列的单独表格,但我认为这样做可能会导致更复杂的搜索查询(许多JOIN)或更多的查询按搜索运行。

对于任何提出的解决方案,请您说明为什么您认为这样做很合适?

2)我的另一个问题(希望在下面明确说明)是我的设计目前包含一个"服务类型"表格我将定义每个产品的核心类型,其中每个服务都是一个"实例"给定产品。

我的问题是,如果我同时拥有产品和服务类型表,我觉得我可能最终会复制大部分内容。所以为了避免这种重复是我在设计中试图实现的另一个主要问题。

更多详情

我目前正在撰写一个自定义网络应用程序,用于跟踪按客户提供的服务,不仅用于开票(结算周期,开始/结束日期,价格),还包括这些服务的文档(关联的用户帐户,IP地址,物理资产等。)

每项服务均基于"产品"表定义基本产品的名称,价格,开票时间,描述等...我们可以有多个相同类型的产品(例如,对于给定产品类型的不同计划)。例如,我们有以下产品:

  • 共享WebHosting Plan One
  • 共享WebHosting Plan Two
  • 共享WebHosting计划三
  • 专用服务器计划
  • Virtual Dedicated Server Plan One
  • Virtual Dedicated Server Plan Two

现在我遇到的问题是,我们有许多字段,这些字段对于任何给定的服务都是通用的,但是我们还有许多字段会根据" type"而改变。正在跟踪的服务。根据服务的类型,我将显示所有服务的基本表单,还会显示添加/编辑等的相应表单...

例如,我们有以下服务类型,每个产品(如上所示)都与这些核心服务类型之一相关:

  • 共享虚拟主机
  • 专用主机
  • Virtual Dedicated Hosting
  • ADSL
  • ...

我可能的解决方案

当前解决方案 - 多个表

目前,在我的数据库中,我有:

ServiceTypes

  • ServiceTypeID INT PK
  • 类型VARCHAR(40)

产品

  • ProductID INT PK
  • 名称VARCHAR(40)
  • 说明文字
  • 价格DECIMAL
  • BillingDuration INT
  • TypeID INT(FK ServiceTypes.ServiceTypeID)

服务

  • ServiceID INT PK
  • ProductID INT(FK:Product.ProductID)
  • 名称VARCHAR(40)
  • 说明文字
  • 价格DECIMAL
  • BillingDuration INT
  • Active BIT
  • StartDate DATETIME
  • EndDate DATETIME

这些是任何服务的主要表格,然后我有扩展属性的附加表格:

ServiceADSLInfo

  • ServiceADSLInfoID INT PK
  • ServiceID INT(FK:Service.ServiceID)
  • FNN VARCHAR(10)
  • 用户名VARCHAR(20)
  • 密码VARCHAR(20)
  • LocationID INT(FK:Locations.LocationID)
  • ModemAssetID INT(FK:Assets.AssetID)

ServiceVirtualServerInfo

  • ServiceVirtualServerInfo INT PK
  • ServiceID INT(FK:Service.ServiceID)
  • ServerName VARCHAR(20)
  • IPAddress INT(FK:IPAddresses.AddressID)
  • HostServer INT(FK:Assets.AssetID)
  • 用户名VARCHAR(20)
  • 密码VARCHAR(20)

ServiceSharedHostingInfo

  • ServiceSharedHostingInfoID INT PK
  • ServiceID INT(FK:Service.ServiceID)
  • 主机名VARCHAR(50)
  • HostServer INT(FK:Assets.AssetID)
  • DiskSpaceQuota INT
  • BandwidthQuota INT

其他解决方案 - 单表

我想将所有与服务相关的信息存储在单个表中,而不管服务类型如何,如果该特定服务不需要,则只需将值设为NULL。

  • ServiceID INT PK
  • ProductID INT(FK:Product.ProductID)
  • 名称VARCHAR(40)
  • 说明文字
  • 价格DECIMAL
  • BillingDuration INT
  • Active BIT
  • StartDate DATETIME
  • EndDate DATETIME
  • 用户名VARCHAR(20)
  • 密码VARCHAR(20)
  • FNN VARCHAR(10)
  • LocationID INT(FK:Locations.LocationID)
  • AssetID INT(FK:Assets.AssetID)
  • ...

我觉得在搜索方面这可能是一个更简单的解决方案,因为为了服务任何与服务相关的数据,我可以在单个表上使用全文搜索,而不用担心加入记录在一起。

我主要担心的是,我最终会得到一个包含30多列的表,这看起来可能会非常混乱。另一件事是,它并没有解决我的问题,因为我仍然需要核心serviceTypes表来确定我需要为任何给定的搜索使用哪些字段 - 因此仍然与我的产品有一些重叠表

我想知道是否无法避免与产品表的某种程度的重叠?

实体 - 属性 - 值模型

我也考虑过这个设计。总的来说,我觉得这对我来说太过分了,因为我不需要那些 灵活和动态的东西。我们需要一组字段,具体取决于服务类型,但我们需要在每种核心服务类型上收集的数据我都看不到很快就会改变,所以这可能是静态的。

在我看来,实现这种灵活性所需的应用程序逻辑对于它带来的好处来说太复杂了。

必须根据从数据库中查询的字段类型确定要显示的HTML表单字段的类型......听起来很痛苦。

如果我能提供进一步的详细信息,请告诉我们!我希望一切都清楚。

谢谢!

1 个答案:

答案 0 :(得分:2)

我认为这一切都取决于你如何设想前进,特别是新服务进入系统,所有都是有效的方法,但都有利有弊。

使用第一种方法可以获得更清晰的主表,但是对于每个服务,您必须创建一个单独的表,对于新服务,您将不得不继续这样做,对于您的应用程序,这可能会增加一些复杂性,因为每个服务将需要自己的一组查询来提取数据(不知道你的架构在这里是什么,所以在黑暗中刺伤。我个人认为这最终会受到伤害。

非规范化表方法更容易查询,但是您可以创建一个包含大量某些类型的有用数据的怪物表。稍微不同的方法可能是添加通用字段,即名为numX的10个字段(其中x为1到10),其中包含数字,10个名为textx,依此类推,我认为salesforce将此aporoach用于客户的自定义字段。

关键值字段方法就像你说的最灵活,但是你丢失了类型识别之类的东西,至少在数据库中所有东西都需要是同一类型。

这取决于你的应用程序的性质,5个并发用户的性能不应该是关注,所以也许应该是易于实现。通用方法概述(销售人员方法)可能在这里工作,并可能覆盖您前进的其他服务以及将来证明您的一点,但这取决于您设想的变化。

如果变化是一致的,那么加载具有不同字段的服务等等,键/值方法可能是你最好的选择,但在那个阶段你也可以看一些nosql方法,因为它们可能适合这里的账单,但是mysql仍然有用,只是打开讨论。

<强>更新

继续评论,如果你没有设想太频繁的服务,我会跳过noSQL,因为它会增加你的开发的复杂性,可能不会让你受益。

如上所述,服务类型可能不会改变太多,我认为非规范化,通用方法可能对您有用。这样,您的应用程序可以有一个服务区域,您可以将其他属性视为“自定义字段”并根据需要添加。那样你的app就是通用的。一个不幸的副作用是你必须通过某种逻辑以某种方式在你的应用程序中管理它,以测试它是否存在,并且你将不得不拉出所有字段,无论它们是否已填充,目前您的需求,可能不是一个巨大的权衡。

通用方法的示例(非常非常简单)示例。

enter image description here

  • 通用字段是您在所有服务中共享的主要字段。

这可能会使搜索变得有点痛苦,因为您可能(取决于机制)必须在搜索中包含所有字段