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

标签 php mysql database-design application-design



1)我正在寻找一种设计Web应用程序的适当方法,尤其是数据库架构,以便可以拥有一个基表,其中包含给定服务的所有核心字段,然后根据服务的类型,将需要与服务关联的其他字段集。

我需要以一种简单的方式执行搜索并提供合理的性能。我可能正在看某种类型的全文本搜索,但是最多只有5个应用程序的并发用户。

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

对于提出的任何解决方案,您能否指定为什么您认为这很合适?

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

我在这里的问题是,如果我同时具有产品和服务类型表,那可能会导致大多数重复的事情。因此,避免重复是我在设计中要实现的另一主要目的。

更多细节

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

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


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


现在,我的问题是,对于给定的服务,我们有许多字段,但是根据要跟踪的服务的“类型”,我们也有很多字段在变化。根据服务的类型,我将显示所有服务的基本表单,但还会显示用于添加/编辑等的适当表单。

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


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


我可能的解决方案

当前解决方案-多表

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

服务类型


ServiceTypeID INT PK
类型VARCHAR(40)


产品


产品编号INT PK
名称VARCHAR(40)
说明文字
价格十进制
BillingDuration INT
TypeID INT(FK ServiceTypes.ServiceTypeID)


服务


服务ID INT PK
ProductID INT(FK:Product.ProductID)
名称VARCHAR(40)
说明文字
价格十进制
BillingDuration INT
活跃BIT
StartDate DATETIME
结束日期DATETIME


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

服务ADSLInfo


服务ADSLInfoID 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
带宽配额INT


其他解决方案-单桌

我正在考虑将所有与服务相关的信息存储在一个表中,而与服务的类型无关,并且如果该特定服务不需要它们,则将它们的值设置为NULL。


服务ID INT PK
ProductID INT(FK:Product.ProductID)
名称VARCHAR(40)
说明文字
价格十进制
BillingDuration INT
活跃BIT
StartDate DATETIME
结束日期DATETIME
用户名VARCHAR(20)
密码VARCHAR(20)
FNN VARCHAR(10)
LocationID INT(FK:Locations.LocationID)
AssetID INT(FK:Assets.AssetID)
...


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

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

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

实体-属性-价值模型

我也考虑过这种设计。总的来说,我觉得这对我来说太过分了,因为我不需要那么灵活和动态。根据服务类型,我们将需要一组字段组,但是我们无法很快看到需要在每种核心服务类型上收集的数据,因此这可能是静态的。

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

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

如果可以提供更多详细信息,请告诉我!我希望一切都清楚。

谢谢!

最佳答案

我认为这一切都取决于您如何设想向前发展,特别是随着系统中新服务的加入,这些都是有效的方法,但是各有利弊。

使用第一种方法,您可以获得更干净的主表,但是对于每个服务,您必须创建一个单独的表,对于新服务,您将必须继续执行此操作,对于您的应用程序,这可能会增加一些复杂性,因为每个服务将需要自己的服务一组查询以提取数据(不确定您的体系结构在这里是什么,所以很暗。我个人认为这样做最终会很痛苦。

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

键值字段方法就像您说的那样最灵活,但是却丢失了诸如类型识别之类的东西,至少所有东西在数据库中都必须是同一类型。

这取决于您的应用程序的性质,不应同时考虑5个并发用户的性能,因此应该易于实施。通用方法概述(销售人员方法)可能在这里起作用,并且可能涵盖其他服务的向前发展和对您的未来证明,但这取决于您所设想的变化。

如果更改将是一致的,则加载具有不同字段等服务的服务,而键/值方法可能是您最好的选择,但是在此阶段,您还可以查看一些nosql方法,因为它们可能适合这里的要求,但是mysql仍然有效,只是打开讨论。

更新资料

与评论保持一致,如果您不希望对服务进行太频繁的更改,我会跳过noSQL,因为这会给您的开发增加复杂性,可能对您没有好处。

如前所述,服务类型可能不会发生太大变化,然后我认为非规范化的通用方法可能对您有用。这样,您的应用程序可以在一个服务区域中使用,并且可以将其他属性视为“自定义字段”,并根据需要进行添加。这样,您的应用就是通用的。不幸的一个副作用是,您将不得不通过某种逻辑在应用程序中以某种方式管理它,以测试它是否存在,并且您将不得不拉出所有字段(无论是否填充了这些字段),以满足您当前的需求巨大的权衡。

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




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


这可能会使搜索有些麻烦,因为您可能(取决于机制)必须在搜索中包括所有字段

关于php - 具有不同字段集的记录的数据库设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13191314/

相关文章:

php - 运行这段代码时会发生什么?

PHP SHA256 和 Salt 不起作用

mysql - 使用 MySQL 创建简单修订系统的最佳方法是什么?

mysql - 将日期和时间格式化为 MySQL 默认格式

PHP Mysqli fetch_assoc

database - 有没有在数据库中存储矢量信息的标准方法?

database - 使用对象角色建模 (ORM) 的关系模型中的动态类型

php - 上传文件在php中不起作用

php - 如何在 Yii2 Framework 中使用带有更多标签的链接中的图像

mysql - 在我们更新 Mysql 版本时需要使用 @ 更改 MYSQL 查询