0

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

一个列表中的所有类型的项目
假设您有项目列表。你可以有一个 CD 列表、一个 DVD 列表和一个书籍列表。这意味着 1 个列表在数据库术语中有许多项目,列表的 id 在项目行中。
但是,如果您想列出所有与超级马里奥相关的东西,包括原声 DVD、那部可怕的真人电影和一些基于水管工生活的同人小说,该怎么办。
我突然意识到,在绘制我的数据库时,那些属于同一个列表的项目不能在同一个表中,因为它们都有不同的列来支持艺术家/专辑标题、导演/电影标题、作者/小说标题等。我不可能把所有东西都放在一张大桌子上。
最重要的是,我想在我的数据库中拥有原声专辑的曲目标题和电影的演员。如果我只有 CD,我可以轻松地将专辑曲目表附加到我的项目表,但我不能只是将各种不同的表附加到我的项目表,因为如果我这样做对性能来说不会太好想要获取某个列表的所有项目及其所有详细信息。该程序必须搜索所有附加的表格以查找列表的引用,即使该列表不包含任何书籍、黑胶唱片、漫画、电视剧、植物、家具等……</p>

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

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,来自另一个表,附加到项目。那将是一个有很多记录的表,这再次提出了我的问题:这对性能不是很糟糕..?

我真诚地希望有人能给我一些关于此事的见解..

4

1 回答 1

4

完全通用的数据库可能是个坏主意——这通常意味着您必须在应用程序级别完全强制执行数据一致性。当您想在运行时避免 DDL 时,这对于高度“非类型化”或“易失性”数据可能是合理的,但您在此处描述的数据对于更传统的数据库设计而言看起来足够“类型化”。

根据您的描述,您需要类似以下内容:

在此处输入图像描述

在此处输入图像描述符号表示“类别”(又名继承、子类型、泛化层次结构等)。

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

此外,我们可以通过 GROUP 和 GROUP_ITEM 对不同类型的项目进行分组(例如,马里奥原声带、电影和书籍可以分组在一起,在同一个 GROUP_ID 下)。

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


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

如果这在性能方面出现问题,则:

  • 定期执行此操作,缓存结果并使用有些过时的结果。
  • 或在修改数据时缓存结果(通过触发器),但要非常小心以避免并发环境中的异常。

    例如...

    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 的事务隔离和锁定。

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

于 2012-06-26T11:45:27.700 回答