【问题标题】:Database design for records with different sets of fields具有不同字段集的记录的数据库设计
【发布时间】:2012-10-22 21:08:29
【问题描述】:

问题

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

我需要以这样一种方式执行此操作,即执行搜索将是直截了当的并提供合理的性能。我可能正在研究某种类型的全文搜索,但该应用程序最多只有 5 个并发用户。

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

对于提出的任何解决方案,您能否具体说明您认为这很合适的原因?

2) 我的另一个问题(希望下面会清楚)是我的设计目前包含一个“服务类型”表,我将在其中定义每个产品的核心类型,其中每个服务然后是给定产品的“实例”。

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

更多详情

我目前正在编写一个自定义 Web 应用程序,用于跟踪基于每个客户提供的服务,不仅用于开票(计费周期、开始/结束日期、价格),还用于记录这些服务(关联用户帐户、IP 地址、实物资产等)。

每项服务都基于一个“产品”表,该表定义了基本产品的名称、价格、计费期限、描述等......我们可以有多个相同类型的产品(例如,对于不同的计划给定的产品类型)。例如,我们有以下产品:

  • 共享虚拟主机计划一
  • 共享虚拟主机计划二
  • 共享虚拟主机计划三
  • 专用服务器计划
  • 虚拟专用服务器方案一
  • 虚拟专用服务器方案二

现在我遇到的问题是,我们有许多对任何给定服务都通用的字段,但我们也有许多字段会发生变化,具体取决于被跟踪的服务的“类型”。根据服务的类型,我将显示所有服务的基本表单,以及用于添加/编辑等的适当表单...

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

  • 共享虚拟主机
  • 专用主机
  • 虚拟专用主机
  • ADSL
  • ...

我可能的解决方案

当前解决方案 - 多个表

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

服务类型

  • ServiceTypeID INT PK
  • 类型 VARCHAR(40)

产品

  • ProductID INT PK
  • 名称 VARCHAR(40)
  • 描述文本
  • 十进制价格
  • BillingDuration INT
  • TypeID INT (FK ServiceTypes.ServiceTypeID)

服务

  • ServiceID INT PK
  • ProductID INT (FK: Product.ProductID)
  • 名称 VARCHAR(40)
  • 描述文本
  • 十进制价格
  • BillingDuration INT
  • 活动位
  • 开始日期日期时间
  • 结束日期日期时间

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

ServiceADSLInfo

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

ServiceVirtualServerInfo

  • ServiceVirtualServerInfo INT PK
  • ServiceID INT (FK: Service.ServiceID)
  • 服务器名称 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)
  • 描述文本
  • 十进制价格
  • BillingDuration INT
  • 活动位
  • 开始日期日期时间
  • 结束日期日期时间
  • 用户名 VARCHAR(20)
  • 密码 VARCHAR(20)
  • FNN VARCHAR(10)
  • Lo​​cationID INT (FK: Locations.LocationID)
  • AssetID INT (FK: Assets.AssetID)
  • ...

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

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

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

实体-属性-值模型

我也考虑过这种设计。总的来说,我觉得这对我来说太过分了,因为我不需要让事情变得那种灵活和动态。我们将需要一组取决于服务类型的字段,但我们需要收集的每种核心服务类型的数据我看不到很快会发生变化,所以这可以是静态的。

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

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

如果我可以提供任何进一步的细节,请告诉我!我希望一切都清楚。

谢谢!

【问题讨论】:

    标签: php mysql database-design application-design


    【解决方案1】:

    我认为这一切都取决于您对前进的设想,尤其是在新服务进入系统的情况下,所有这些都是有效的方法,但各有利弊。

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

    非规范化表方法更容易查询,但您可能会创建一个包含大量针对某些类型的不必要数据的怪物表。稍微不同的方法可能是添加通用字段,即 10 个称为 numX 的字段(其中 x 是 1 到 10),其中包含数字,10 个称为 textx 等等,我认为销售人员使用这种方法为客户自定义字段。

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

    这取决于您的应用程序的性质,5 个并发用户的性能不应该是问题,所以也许应该是易于实施。通用方法大纲(销售人员方法)可能适用于此,并可能涵盖您的其他服务,并为您提供一点未来证明,但这取决于您设想的变化。

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

    更新

    根据评论,如果您不打算对服务进行过于频繁的更改,我会跳过 noSQL,因为它会增加您的开发的复杂性,这可能不会使您受益。

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

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

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

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

    【讨论】:

    • 感谢您的反馈。欣赏它。我真的不认为所提供的不同服务会有很多变化,因为我们是一家 ISP,只有这么多核心产品。更多的是产品会改变,这就是为什么我到目前为止将这些产品作为一个单独的实体。但是我们很少会添加一个需要单独信息的全新类型。没想到NoSQL,还没用过,但一定会研究一下。
    • 没问题,已根据您的评论更新了答案,并提供了更多详细信息。 HTH
    • 谢谢!您对如何处理我的产品和服务类型记录之间的重叠有意见吗?我知道那里可能没有什么可做的,因为这是接近它的最好/最简单的方法。但这只是让我烦恼的是会有一定程度的重叠。
    • 你说的是列重叠吗?
    • 不,只是我的 ServiceTypes 和 Products 表之间的重叠。例如,在 ServiceTypes 中,我会使用 Shared Web Hosting、ADSL、VOIP。在产品中,我可能有 Shared Webhosting Shared Web Hosting Plan1、Shared Web Hosting Plan2、ADSL Plan 1、ADSL Plan 2、Hosted VOIP。看看有多大程度的重叠?但我觉得我需要两张桌子。
    猜你喜欢
    • 2023-03-24
    • 2021-12-18
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多