3

我将不同的项目(笔记、文章、图片、文件)存储在一个表中(所有项目类型都有许多共同的元数据 - 例如,类别、标签、评级、统计信息等)。

我的第一个设计是这样的:表Items,加上每个项目类型(NoteItemsArticleItemsPictureItems等)的另一个“详细”表。要检索单个项目,表必须一对一连接(SELECT * FROM Items INNER JOIN PictureItems ON Items.Id = PictureItems.Id WHERE Items.Id = N)。

我很确定这种“按部就班”的设计会很好地工作(多次这样做),但是,我开始怀疑这种设计是否是矫枉过正。拥有一个表(Items)会简单得多。

假设有大约 5% 的图片或文件类型的项目。

现在,问题是:如果我选择(几乎)单表设计,那么无论如何都有图像字段的详细表会更好(当然,对于图片和文件项)?

场景一:只有一张表:Items(用于存放笔记、文章、图片、文件...)

场景二:两张表:Items(用于存储笔记、文章、图片文件)、ImageItems(仅用于存储item类型图片、文件的图片字段);一对一的关系

(场景 3 是场景 2 的一个小变体;有 3 个表(项目、图片项目、文件项目))

方案 1 的优点是:

  • 更简单的选择查询(无连接)
  • 无事务更新(INSERT/UPDATE 仅更新一张表)
  • 无事务更新带来的性能、可扩展性?

方案 2 的优点是:

  • 更清洁的设计
  • 较低的数据消耗(在场景 1 中,除了图片或文件之外,大约 95% 的类型项在图像字段中具有 NULL 值,即浪费了大约 16 个字节用于指针)

您会选择哪种方案:1(无事务更新)或 2(更低的数据消耗)?感谢您的意见。

4

4 回答 4

2

如果程序员足够明智地只从表中查询所需的列而不是“SELECT *”,那么第一种设计方法看起来还可以。

需要为第二个设计处理索引、引用约束等。

于 2008-12-02T13:58:45.990 回答
0

如果您使用某种 ORM 或自动生成 DAL(SubSonic?),第一种方法通常会受到惩罚。每次传递 DAL 对象(或集合)时,您都会检索 Image 列(及其数据),所以通常我将使用场景 2(或 3)

从 SQL 的角度来看,根据您的存储引擎(ISAM、InnoDB 等),两种场景的工作方式大致相同,但即便如此,场景之间的好处和差异也很小。

于 2008-12-03T21:46:23.533 回答
0

如果你是对的,只有大约 5% 的行实际上有额外的图像/二进制数据,那么我肯定会说使用单表方法,并结合 Murthy 给出的提示 - 确保不要在这张表上执行 SELECT * ,但只请求您真正需要的那些列 - 尽可能多地省略 BLOB 列。

如果您的数据库增长,您可能还想为 BLOB 数据检查一个单独的文件组,以保持分离和清洁(但这实际上只有在您处理数十万行或更多行时,并且如果您可以拆分文件组到几个单独的磁盘上)。

KISS - 保持智能和简单 - 尽可能!:-)

马克

于 2009-02-05T21:39:33.603 回答
0

如果数据库不需要知道这些项目中的内容(不会对它们进行索引或搜索),那么选项 1 似乎是最好的选择(假设您只有一个“项目”列作为 BLOB)-您可以阅读将项目作为二进制数据取出并自行处理 - 从而避免内部连接。

我不相信方案 2 会降低数据消耗 - 您可以只使用 BLOB 字段(无论如何,额外的 ImageItems 表的开销可能相当于每行 16 个字节)

所以我个人会选择选项 1,但当然这取决于您在项目从数据库中出来时如何处理它们。

于 2008-12-02T11:07:45.820 回答