1

我的软件几天前投入生产,现在我想就数据库结构进行一些争论。

软件收集船舶数据,目前每艘船舶有174个详细信息,每个详细信息可以是文本值、长文本值、数字(指定长度,有或没有指定小数位数)、日期、日期随着时间的推移,一个布尔字段,一个包含许多值的菜单,一个数据列表等等。

我用下表解决了这个问题

船:
- ID - smallint,自动增量标识
- IMO - int,一个在船舶寿命期间不会改变的数字

ShipDetailType:
- ID - smallint,自动增量标识
- 描述 - nvarchar(200),字段包含的值的描述
- Position - smallint,字段在数据输入表单中的位置
- ShipDetailGroup_ID - smallint,数据输入表单中字段所属组的键
- 类型 - varchar(4),字段的类型如上所述

ShipDetailGroup
- ID - smallint,自动增量标识
(剪断……)

ShipMenuPresetValue
- ID - smallint,自动增量标识
- ShipDetailType_ID - smallint,值所属详细信息的键
- Value - nvarchar(100),菜单类型详细信息中预设的值

ShipTextDetail
- ID - smallint,自动增量标识
- Ship_ID - smallint,详细信息所属船舶的密钥
- ShipDetailType_ID - smallint,值的详细类型的 Key
- 文本 - nvarchar(500),包含详细信息值的字段
- 修改日期 - 小日期时间
- User_ID - smallint,用户表的键

船舶文本详细历史
(剪断……)
此表与 ShipTextDetail 相同,包含对详细信息的所有更改。

列表详细信息类型的其他表,每个表都包含列表所需的指定字段,...

我刚刚阅读了这篇文章:http ://thedailywtf.com/Articles/The_Inner-Platform_Effect.aspx和http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID :10678084117056

文章说这不是处理问题的正确方法。

我的客户在更改详细信息描述并添加更多详细信息时具有详细信息和组的管理 gui。

数据输入表单是通过从 DetailGroups 和 DetailTypes 中读取结构动态构建的,每个详细类型生成一个指定的输入控件。

评论表明解决此问题的另一种方法是从表中动态创建和删除列。

你怎么看?

图表截图: http://img24.imageshack.us/my.php?image= 66604496uk3.png

4

4 回答 4

4

如果出现以下情况,我会重构您的代码:

  • 您的客户投诉
  • 你发现了一些不起作用的东西
  • 您发现了一种代码无法处理您知道将来会发生的更改的方法。

您记得编写允许您重构的单元测试,对吧?

*就你那里的结构而言,我以前见过类似的结构。这有点麻烦,但在很多地方都是标准的。要记住的一件事是,虽然可以从数据库中动态添加和删除列,但数据库的内部存储机制并不一定希望您连续添加和删除这些列。但我认为与上述几点相比,这不是很相关,归结为:*它有效吗?

于 2009-02-12T00:50:09.013 回答
4

我以前见过这种方法,一旦数据量增加,它就会出现大量的性能问题。当您需要返回多个项目并在 where 子句中使用多个条件时,您会遇到这种问题。您在 Ship 和 ShipTextDetail 之间来回加入以获得所有选择的列 - 也许您必须这样做 10/20 次?然后你对你的标准做同样的事情可能 2-3 次。现在您有一个包含如此多连接的查询,它运行速度非常慢。接下来,您“预煮”一些数据以提高性能,即将常用数据拖到固定表结构中 - 啊,您已经返回到半规范化模型。

我的建议是——你知道 174 个字段的信息,这些是你的核心属性。您的客户可能会添加到该列表中,并且可能会更改字段的描述,但这仍然是一个非常好的起点。围绕这些创建一个适当的 DataModel,然后构建一个可扩展性机制,就像您已经完成的那样,但仅适用于新字段。元数据——字段的描述,可以驻留在另一个表中,或者可能驻留在资源文件中(对国际化有用吗?),这为现有字段提供了一些灵活性。

我同意乔的观点,如果您的数据库很小,即 <1000 艘船并且您的选择很简单,您可能不会遇到问题。尽管有 174 个属性可供选择,但这似乎不太可能。我认为您应该首先更改一些“显而易见”的字段,即我假设您有 Ship.Name、Ship.Owner、Ship.Weight、Ship.Registration ...

祝你好运。

于 2009-02-12T03:11:57.987 回答
0

我做过类似的事情,但是这个特定的实现有几个问题:

  1. 您将数字、布尔值、日期等存储为字符串。这可能不太理想。另一种方法是为不同的数据类型实现单独的类(从基类继承),然后将它们存储在为它们的数据类型制作的表中。
  2. 您跟踪的属性是否经常更改?每个油轮有不同的设置吗?如果没有,最好制作对象而不是属性包来存储所有数据。然后可以将这些对象持久化到数据库中。
于 2009-02-12T01:14:58.503 回答
0

从性能的角度来看,任何一种方法都可以。可能有多少艘船?所有数据都将适合任何服务器上的 RAM。

于 2009-02-12T18:06:54.343 回答