大量列的数据库模式设计

时间:2015-02-18 02:04:17

标签: oracle database-design

我有一个用例,我需要为例如参考数据建模不同口味的冰淇淋。说我有50种口味的冰淇淋: -

  • 20个属性,例如所有口味都可以分享冰冻,奶油味。
  • 每种口味的冰淇淋都有20-30个属性,不会与其他口味共享,例如: -
    • 草莓冰淇淋可能会跟踪酸味,水果百分比等。
    • 巧克力冰淇淋可能会追踪苦味,可可等等。

我如何在数据库模型中整齐地建模这些数据,纯粹是从存储/检索的角度来看?

我能想到的选择: -

  1. 每种味道一张桌子。这将需要50个表,每个表将有20个彼此重叠的列,以及另外20-30个属性,这些属性将是独特的。
    • 优点:很好地模拟每种风味的数据
    • 缺点:列重叠和需要大量表格
  2. 所有口味的一张桌子。这只需要1个表,但需要1000多列,其中大部分都是空的。
    • 优点:一般来说,很好地模拟冰淇淋的数据
    • 缺点:大量的列和大量的浪费'空间
  3. 所有风味的一个键值表,包含flavor Id,属性名称和属性值。
    • 优点:最简单的创建和插入数据
    • 缺点:难以提取,不是真正的数据模型本身,难以形成属性约束,或者与其他属性相关的属性

5 个答案:

答案 0 :(得分:0)

我有一个包含所有公共属性的表,然后是另一个用于非共享属性的表。例如:

CREATE TABLE ICE_CREAM_FLAVOR
  (FLAVOR          VARCHAR2(100) PRIMARY KEY,
   FREEZING_TEMP   NUMBER,
   CREAMINESS      NUMBER,
   ETC             VARCHAR2(25),
   BLAH            NUMBER);

CREATE TABLE ICE_CREAM_FLAVOR_ATTRIBUTE
  (ID_ICF_ATTRIBUTE  NUMBER,  -- should be populated by an insert trigger
   FLAVOR            VARCHAR2(100)
     NOT NULL
     REFERENCES ICE_CREAM_FLAVOR(FLAVOR),
   ATTRIBUTE_NAME    VARCHAR2(25),
   ATTRIBUTE_VALUE   VARCHAR2(100));

您的里程可能会有所不同。

分享并享受。

答案 1 :(得分:0)

我想建议,你可以创建3个不同的表。

  1. 冰淇淋口味:您可以储存所有口味的冰淇淋。它将是icecream_flavor_master表。如果你有50种口味可以创造出来,比如草莓,巧克力等。

  2. 冰淇淋属性:您可以存储冰淇淋的所有属性。它将是icecream_attribute_master表。假设你有50个属性而不是50行会产生,如酸味,苦味,水果百分比,可可水平等。

  3. 冰淇淋口味属性:您可以在此表中存储icecream_flavor_master和icecream_attribute_master的主键,以制作冰淇淋的风味和属性之间的关系。

  4. 让我知道更多信息。

答案 2 :(得分:0)

绝不存储错误类型的值。

enter image description here

无论您选择何种设计,请确保以自然格式存储值。使用NUMBER,DATE,VARCHAR2,CLOB,XMLTYPE,CLOB(IS JSON),TIMESTAMP等。试图填充字符串中的所有内容会导致许多问题。您将失去验证,便利性,性能和类型安全性。

例如,这是一个常见的类型安全问题。想象一下这个简单的查询,找到超过25%水果的冰淇淋:

select *
from   ice_cream_flavor_attribute
where  attribute_name = 'Fruit Percentage'
   and attribute_value > 25;

你看到了这个bug吗?您是否看到具有相同数据的同一查询可能会在某一天工作并且使用ORA-01722: invalid number使其失败?

编写强制Oracle以特定顺序评估条件的查询很困难。重新排序谓词将无济于事(99.9%的时间)。添加内联视图无济于事(99.9%的时间)。使用CASE语句将有效,但不是100%的时间。使用提示将起作用,但是很棘手。使用内联视图和ROWNUM是我解决问题的首选方法,但它看起来很奇怪而且难以理解。


如果您必须使用实体属性值模型(如果您有超过1000个属性,则可能是不可避免的),至少使用正确的类型。

不要担心空间 - 空列最多使用1个字节。

不要担心像“但我们的查询更复杂,我们总是需要知道使用哪个列!” - 实际上,在不知道其类型的情况下,您可以对值进行任何有用的操作。每次读取或写入值时,您都必须考虑类型。

答案 3 :(得分:0)

您可以将flavor分类为各种口味,即共享某些属性的口味。这适用于扩展其他类的类和子类。

如果您想对此进行ER建模,请在网络上查找“概括/专业化”。一些网站将此称为“扩展ER建模”或EER。

如果要设计关系表来实现ER设计,请查看两种模式:单表继承和类表继承。
https://stackoverflow.com/tags/single-table-inheritance/info

https://stackoverflow.com/tags/class-table-inheritance/info

另外,请看看Martin Fowler在网络上或在他的一本教科书中对这个主题的处理。

答案 4 :(得分:0)

哪些大型供应商正在为ECM(企业内容管理)中的大量数据做些什么,在这种情况下,您有一个非常相似的场景(许多自定义类具有自定义属性,其中一些可能是相同的,具有各种类型的属性): / p>

  1. 所有风味的一个键值表,包含flavor Id,属性名称和属性值。
  2. 他们每种类型使用一个键值表(字符串,数字,日期等)。

    对于性能优化,它们允许为属性定义专用表,以便保持索引较小而不会拥挤其他属性。

    专用表适用于:

    • 大量使用(包含多行)
    • 糟糕的直方图(如旗帜)

    否则Oracle索引可能被欺骗,而全表访问是最快的访问,这将是非常糟糕的。 因此,在拥有大量数据时,请尽早考虑性能。