数据库设计(许多不同项目的列表,带有自定义字段)

时间:2012-06-26 10:10:24

标签: database performance forms database-design referential-integrity

我正在开展一个你可以处理各种物品的项目。它是什么并不重要,这是我担心的数据库设计。如果有人能给我一些关于如何为此创建数据库布局的信息,或者只是指出我正确的方向,我将非常感激。

一个列表中的各种项目
想象一下,你有物品清单。您可以拥有CD列表,DVD列表和书籍列表。这转换为1个列表在数据库术语中有许多项目,列表的id在项目行中 但是,如果你想要一份包含所有超级马里奥相关内容的清单,包含配乐DVD,那部可怕的真人电影和一些基于水管工生活的小说小说。 我突然意识到,在绘制我的数据库时,那些属于同一个列表的项目不能在同一个表中,因为它们都有不同的列来支持艺术家/专辑标题,导演/电影标题,作者/小说的标题等等。我不可能把所有的都放在一张巨大的桌子里 最重要的是,我想在我的数据库中获得原声专辑的曲目标题和电影的演员。如果我只有CD,我可以很容易地将album_track-table附加到我的item-table,但我不能只将各种不同的表附加到我的item-table中,因为如果我这样做对性能不太好想要获得包含特定列表所有详细信息的所有项目。该程序必须搜索所有附表中的列表参考,即使该列表不包含任何书籍,乙烯基,漫画,电视剧,植物,家具等......

我现在所拥有的是以下布局(但我无法想象这是最好的方法):

t_list (id) --> t_item (id, id_list, image)

t_item --> t_cd (id, id_item, artist, title)
t_item --> t_dvd (id, id_item, director, title)
t_item --> …

t_cd --> t_cd_track (id, id_cd, track_title, length)
t_dvd --> t_dvd_actors (id, id_dvd, actor_name, image)
…

自定义列
现在,想象一下,要将这些项添加到cd列表,根据表t_cd(艺术家,专辑标题,流派,...)中的列,您将拥有一个带有输入字段的表单。我希望能够添加自定义输入字段,例如相册的平均价格 这是为特定用户设置的某个列表。这不是在项目级别设置的,因为这意味着它将被添加到每个人的表单中。我只想将该字段添加到我自己的CD列表中 但是,它仍然需要与项目相关,因为需要在数据库中填写该值。

我正在考虑这样的事情:

t_list (id) --> t_extra_field (id, description, id_list)
t_extra_field --> t_field_value (id, id_extra_field, value)

但我不完全确定在我的数据库方案中将其附加到哪里。

这种结构能否解决我之前的问题? (t_field --> t_field_value)如果是这样,我也不知道在哪附上。或许列出,就像我在上面的例子中所建议的那样? 这意味着某个项目的所有详细信息都在一个表中,但是按值而不是单个记录,根据某种类别ID,来自另一个表,附加到项目。那将是一张包含大量记录的表格,这再次提出了我的问题:这对性能不是很糟糕吗?

我真诚地希望有人可以就此事给我一些见解。

1 个答案:

答案 0 :(得分:4)

完全通用的数据库可能是一个坏主意 - 它通常意味着您必须在应用程序级别完全强制执行数据一致性。当您希望在运行时避免使用DDL时,这可能适用于高度“无类型”或“易变”数据,但您在此处描述的数据看起来“打字”足以进行更传统的数据库设计。

根据您的描述判断,您需要类似的内容:

enter image description here

enter image description here符号表示“类别”(又称继承,子类型,泛化层次等)。

对于我们确切知道项目应如何连接的特定情况,我们可以直接通过特定子类型之间的链接(也称为联结)表对其进行建模,如TRACK表的情况。

此外,我们可以通过GROUP和GROUP_ITEM对不同种类的项目进行分组(例如,在同一GROUP_ID下,可以将Mario音轨,电影和书籍组合在一起)。

艺术家也以相当普遍的方式处理,因此我们可以轻松地表示(例如)同一个人同时写一首歌和一本书的情况。


对于诸如“专辑的平均价格”之类的东西,理想情况下你根本不应该存储它们 - 你应该根据现有数据在需要时计算它们,所以过时结果的可能性是消除。

如果这在性能方面成为问题,可以:

  • 定期进行,缓存结果并使用过时的结果。
  • 或在修改数据时通过触发器缓存结果,但要非常小心地避免在并发环境中出现异常。

    例如......

    SELECT AVG(PRICE) FROM TABLE1;
    INSERT TABLE2 (AVERAGE_PRICE) VALUES (result_of_the_previous_query);
    

    ...几乎肯定不安全,但依赖于DBMS甚至......

    INSERT TABLE2 (AVERAGE_PRICE) VALUES (SELECT AVG(PRICE) FROM TABLE1);
    
    如果没有适当的锁定,

    ......可能不是完全安全的。您需要了解DBMS的事务隔离和锁定。

    在计算平均值的特定情况下,您可以考虑其他技巧,例如单独递增/递减COUNT并通过每个INSERT / UPDATE / DELETE的触发器添加/减去价格的SUM,然后计算AVG即时。 SQL保证UPDATE MY_COUNT = MY_COUNT + 1之类的东西是“原子的”。