在关系数据库中为可能的空值创建另一个表是否更好?

and*_*112 5 mysql performance null database-design relational-theory query-performance

我正在设计一个在MySQL中使用的关系数据库。我有下一种情况:在一个表中,有些字段在大多数情况下都是NULL. 这些字段将类似于:

Table name: tabla

Fields:
  idtabla not null,
  text (varchar(n)) not null,
  image (mediumblob) {this can be null}
Run Code Online (Sandbox Code Playgroud)

疑问:是否最好创建另一个表,当需要使用图像时,查询新表?为什么您的解决方案更适合设计?MySQL的时间响应、查询的便捷性等?

Dav*_*ett 3

您在这里触及了一个近乎哲学的论点:是否应该允许 NULL 值,因为它们违反了关系数据库模型的“封闭世界”假设(请参阅http://en.wikipedia.org/wiki的相关部分) /Null_(SQL)和这里的许多其他问题,例如为什么我们不应该允许 NULL?有关更多说明)。为了避免未知值将可能未知(或根本不适用于所有情况)的属性拆分为它们自己的关系(表),以便您没有未知的值,但如果值未知,则它根本不存在。虽然这满足了理论,但实际意义却使其不太理想:

  • 在大多数 RDBMS 中,操作JOIN并不是免费的,在额外表中搜索属性会增加引擎满足查询所需的工作量。
  • 如果属性的存在不是相互依赖的(即,无论其他属性如何,每个属性都可能是未知的),那么要将此实现得出结论,您有时最终需要每个属性都有一个表。
  • 额外的联接会增加查询的复杂性并降低可维护性。
  • 更新在某些地方也变得不太直观:清空属性现在变成了 DELETE 操作,而更新属性可以是INSERTUPDATE.

当然,在某些情况下,第一点是相反的,打破属性可以提高效率:

  • 大多数 RBDMS 使用基于页面的存储,将可选信息从核心数据中分离出来意味着您可以在给定页面中容纳更多核心数据行。根据您的数据大小、RAM 和存储基础设施,这对于减少某些大型查询所需的 IO 量可能非常重要(但通常情况并非如此:尽量不要在这一点上“过度优化”,至少在没有运行良好基准测试的情况下)确保事情正在改善而不是恶化)。
    当然,这是假设您的查询经过设计,因此它们仅获取所需的内容,因此引擎无论如何都不需要关心额外信息中的绘图。
  • 同样,如果您仅更新INSERT或中的核心信息UPDATE,并且如果您对这些额外属性有约束或触发器,那么在每次行更改时可能会避免此处理。

您的示例看起来像是在存储图像(或至少在 blob 类型列中存储大量数据)。这里有两个额外的注意事项:

  • 大多数数据库引擎无论如何都会“页外”存储大量数据,因此,如果您避免的话,SELECT *无论如何您都会“免费”获得每页行数奖励。
  • 将它们移到其他地方是否允许您在多个实体之间共享大数据,而不是多次存储相同的 blob,或者信息(如果存在)对于给定行是唯一的吗?

tl;dr:所以恐怕没有硬性且快速的答案。我的建议是做任何最适合您的数据概念模型的事情,因此您需要较少的思考来维护。这通常(但并非总是)意味着使用可为 NULL 的列而不是单独的表。除非您的数据确实很大,否则性能差异可以忽略不计。