如何构建(规范化?)物理参数数据库?

时间:2010-04-27 22:17:25

标签: database-design normalization

我有一系列与不同项目相关的物理参数。例如:

Item, p1, p2, p3
a,     1,  2,  3
b,     4,  5,  6
[...]

其中px代表参数x

我可以继续完全按照提供的方式存储数据库;架构将是

CREATE TABLE t1 (item TEXT PRIMARY KEY, p1 FLOAT, p2 FLOAT, p3 FLOAT);

我可以使用以下语句检索所有项目的参数p1

SELECT p1 FROM t1;

第二种方法是使用类似的模式:

CREATE TABLE t1 (id INT PRIMARY KEY, item TEXT, par TEXT, val FLOAT)

如果您有许多参数(就像我一样),这似乎更简单。但是,参数检索看起来很尴尬:

SELECT val FROM t1 WHERE par == 'p1'

你有什么建议?应该选择“旋转”(第一个)版本还是id, par, val(第二个)版本?

非常感谢。

修改

作为参考,我在SQLAlchemy examples站点(垂直映射)中找到了以下持久性模式:

"""Mapping a vertical table as a dictionary.

This example illustrates accessing and modifying a "vertical" (or
"properties", or pivoted) table via a dict-like interface.  These are tables
that store free-form object properties as rows instead of columns.  For
example, instead of::

  # A regular ("horizontal") table has columns for 'species' and 'size'
  Table('animal', metadata,
        Column('id', Integer, primary_key=True),
        Column('species', Unicode),
        Column('size', Unicode))

A vertical table models this as two tables: one table for the base or parent
entity, and another related table holding key/value pairs::

  Table('animal', metadata,
        Column('id', Integer, primary_key=True))

  # The properties table will have one row for a 'species' value, and
  # another row for the 'size' value.
  Table('properties', metadata
        Column('animal_id', Integer, ForeignKey('animal.id'),
               primary_key=True),
        Column('key', UnicodeText),
        Column('value', UnicodeText))

Because the key/value pairs in a vertical scheme are not fixed in advance,
accessing them like a Python dict can be very convenient.  The example below
can be used with many common vertical schemas as-is or with minor adaptations.

"""

4 个答案:

答案 0 :(得分:1)

这是性能与可扩展性的权衡。如果您从不打算再添加px列,我认为您使用第一种方法是安全的,但是,如果您预计将来会有更多px列,您可能需要执行名称/值方法。 / p>

如果最终获得大量数据,名称 - 价值方法可能会对性能产生不利影响。使用静态列方法可以更快地查询。

您也可以使用静态列方法开始混合,并添加对“扩展”表的支持,该表可以关闭项目,以便您以后可以添加其他属性。

答案 1 :(得分:1)

规范化路由是将ID值放在表引用中。

ID     Item
1      a 
2      b 
3      c 


ID     Item    P
1      1       1
2      1       2
3      1       3

答案 2 :(得分:1)

如果你假设px将超过三个值(p1,p2和p3)到p4等等,那么第一种方法将失败,并且继续为p4,p5等添加列似乎是有缺陷的方法

老实说,吸引我的方法是将项目和参数分成不同的表,然后使用链接实体加入它们:

Item
  |
-----
| | |
ItemParameter

| | |
-----
  |
Parameter

这样一个项目可以有很多参数,并且许多项目都可以存在参数。

因此,项目a可以包含参数p1,p2和p3

(Item)
a
(ItemParameter)
a p1
a p2
a p2
(Parameter)
p1
p2
p3

或者项目b可以具有参数p1,p2,p6,p10和p19

(Item)
b
(ItemParameter)
b p1
b p2
b p6
b p10
b p19
(Parameter)
p1
p2
p6
p10
p19

等等

答案 3 :(得分:1)

除了第二种方法的灵活性之外,另一个优点是参数可以是参数表中的行,将有关该参数的数据存储为数据库的一部分,而不是作为模式的列。它也自然地导致数据的RDF三重表示。

顺便说一句,你不需要添加关键字段,使项目和par成为联合主键

CREATE TABLE t1 ( item TEXT, par TEXT, val FLOAT, PRIMARY KEY (item, par))

第二种方法的一个限制是所有参数的值的数据类型必须相同 - 如果所有浮点数都可以,但是为了一般性,这可能必须是字符串,伴随着验证丢失和需要进行程序数据转换。 / p>

查询速度会受到影响,但您可以使用

等查询获取字词的所有参数
SELECT par,value FROM t1 WHERE item='qitem'

比其他方法更容易转换为演示文稿格式。