【问题标题】:Design of a database, based on a data structure基于数据结构的数据库设计
【发布时间】:2009-04-01 04:06:25
【问题描述】:

我有一个类似这样的数据结构:

typedef struct tagSUB_DATA
{
    double measuredValue;
    double standardDeviation;
    double calculatedValue;
    double weightedError;

} SUB_DATA;

typedef struct tagALL_THE_DATA
{
    int aNumber;
    double aDouble;
    SUB_DATA measurements1;
    SUB_DATA measurements2;

} ALL_THE_DATA;

我需要将其存储在关系数据库中。

我的查询涉及measurements1measurements2 这两个字段。显然,它们是同一类型,所以我的第一个想法是“让我们创建一个SUB_DATA 表并在它们之间创建一个外键链接”。

Table: ALL_THE_DATA
Field: ID (int, Primary Key)
Field: aNumber (int)
Field: aDouble (double)
Field: measurements1 (int, Foreign Key referencing SUB_DATA)
Field: measurements2 (int, Foreign Key referincing SUB_DATA)

Table: SUB_DATA
Field: ID (int, Primary Key)
Field: measuredValue (double)
Field: standardDeviation (double)
Field: calculatedValue (double)
Field: weightedError (double)

但是,数据的实际上下文是这样的,measurements1measurements2 是不同事物的测量值(比如说,苹果和 oranges 火箭),它们都恰好需要测量值、标准差等。那么,将测量的苹果和测量的火箭的数据存储在同一个表中是否仍然合适,即使它们使用相同的数据,还是更谨慎地设计它以便火箭和苹果有自己的(设计相同的)表吗?

Table: ALL_THE_DATA
Field: ID (int, Primary Key)
Field: aNumber (int)
Field: aDouble (double)
Field: appleMeasurements (int, Foreign Key referencing APPLE_MEASUREMENTS)
Field: rocketMeasurements (int, Foreign Key referencing ROCKET_MEASUREMENTS)

Table: APPLE_MEASUREMENTS
Field: ID (int, Primary Key)
Field: measuredValue (double)
Field: standardDeviation (double)
Field: calculatedValue (double)
Field: weightedError (double)

Table: ROCKET_MEASUREMENTS
Field: ID (int, Primary Key)
Field: measuredValue (double)
Field: standardDeviation (double)
Field: calculatedValue (double)
Field: weightedError (double)

您认为这两种解决方案中哪一种最好?第一个似乎不那么冗余,但可能有更大的可能存在不一致的数据。或者也许有比我想象的更好的方法来解决这个问题?

干杯!

(请原谅我的 Apples/Rockets 伪数据 - 我无法在此处发布实际代码)

额外信息:
在这种情况下,我们可以确定火箭和苹果以后不会改变它们的字段,所以我不太担心“如果火箭或苹果的字段稍后改变”的情况。

【问题讨论】:

    标签: database-design data-structures


    【解决方案1】:

    如果您的 SUB_DATA 真的是 Apples 和 Rockets(并且总是 Apples 和 Rockets),那么它们都是相同数据结构的实例可能是一个设计问题,并且可能会使您的代码使用起来风险更大。您可能希望使用子类(即使结构没有不同)只是为了区分类型。

    如果您将两者混合到同一个表中,您会冒着想要更改其中一个结构而不是另一个结构的风险,就像您使用同一个类一样。如果将来有这种可能性,那么显然不要在同一张桌子上分享它们。或者,如果它们有共同点,但将来可能会有所不同,您可以使用多个表。

    这听起来可能需要做很多工作,但一个体面的对象关系映射(例如 Hibernate)实际上可以为您很好地处理类层次结构并拆分需要拆分的内容。

    但是无论您做什么,在您 100% 确定哪些内容将保持共同点以及哪些内容可能会发生变化之前,都不要启动您的数据库。

    【讨论】:

    • 嗯。错误的建议。现在启动数据库,并更改它直到你喜欢它。一旦你学到了新东西,就再改变它。
    • 我不同意这种情况。如果您不知道两个关键实体是同一个实体还是不同的实体,最好先仔细考虑而不是稍后重构。我不认为找出身份和类型是过早的优化。
    • 在这种情况下,我们可以确定火箭和苹果以后不会改变他们的领域。
    【解决方案2】:

    你总是有两个测量值吗?如果是这样,您根本不需要打破表格(只需一张表格,其中包含两组用于两次测量的列)。

    Table: ALL_THE_DATA
    Field: ID (int, Primary Key)
    Field: aNumber (int)
    Field: aDouble (double)
    Field: measuredValue1 (double)
    Field: standardDeviation1 (double)
    Field: calculatedValue1 (double)
    Field: weightedError1 (double)
    Field: measuredValue2 (double)
    Field: standardDeviation2 (double)
    Field: calculatedValue2 (double)
    Field: weightedError2 (double)
    

    对于结构之间的非可选 1:1 关系,将子结构嵌入到父表中是可以接受的设计和高效的。

    不过,这使得添加第三种测量类型变得更加困难。

    【讨论】:

      【解决方案3】:

      为什么不创建这两个表,而是让它们继承自一个通用的测量表?

      【讨论】:

      • 如何继承 RDBMS 中的表?
      • 我猜这取决于您使用的数据库,但 POSTGRES 支持 INHERIT。
      • 你可以模拟继承,没那么难,但是很笨重,这就是为什么你使用 ORM 来为你做这件事。
      猜你喜欢
      • 1970-01-01
      • 2015-06-17
      • 1970-01-01
      • 1970-01-01
      • 2013-02-17
      • 2021-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多