最佳数据库结构 - 具有空字段或更多表的“更宽”表?

时间:2010-11-26 15:51:47

标签: database optimization database-design database-optimization

我需要在数据库中添加其他数据,我可以选择修改现有表(table_existing)还是创建新表。

这就是table_existing现在的样子:

table_existing
-------------------------
| ID | SP | SV | Field1 |
| .. | WW |  1 | ...... |
| .. | WW |  1 | ...... |
-------------------------

选项(A)

table_existing
----------------------------------------------------------------------
| ID | SP | SV | Field1 | Field2 | Field3 | Field4 | Field5 | Field6 |
| .. | XX |  1 | ...... | ...... | ...... | ...... | ...... | ...... |
| .. | YY |  2 | ...... | ...... | ...... | ...... | ...... | ...... |
----------------------------------------------------------------------

选项(B)

table_existing would be converted into table_WW_1_data
---------------
| ID | Field1 |
| .. | ...... |
| .. | ...... |
---------------

table_XX_1_data
------------------------
| ID | Field1 | Field2 |
| .. | ...... | ...... |
| .. | ...... | ...... |
------------------------

table_YY_2_data
---------------------------------
| ID | Field1 | Field2 | Field3 |
| .. | ...... | ...... | ...... |
| .. | ...... | ...... | ...... |
---------------------------------

上下文:SP,SV的组合确定将填充的字段的“数量”。例如,(XX,1)有2个字段。 (YY,2)有3个字段。

如果我使用选项(A),我会在“更宽”的表中有许多空/ NULL值。

如果我选择选项(B),我基本上创建了更多的表格......一个用于SP,SV的“每个”组合 - 总共可能有4-5个。但每个都将填充正确数量的字段。 table_existing也会被更改。

从速度的角度来看,最优的数据库结构是什么? 我认为从可维护性的角度来看,选项(B)可能会更好。< / p>


EDIT1

这两个选项都不是我应用程序中最关键/最常用的表。

在选项(B)中,在分割数据之后,根本不需要加入它们。如果我知道我需要XX_1的字段,我会去那张桌子。

我试图了解是否有一个包含许多未使用值的大型表与在更多表中分配相同数据的优缺点。大量的表是否会导致数据库中的性能损失(我们已经有大约80个表)?

5 个答案:

答案 0 :(得分:19)

从速度的角度来看,更优化的数据库结构是什么?

嗯,什么是正确的,最佳实践等,称为规范化。如果你这样做,将没有可选列(不是字段),没有Null。可选列将位于单独的表中,行数较少。当然,您可以安排表格,使它们成为可选列的集合,而不是(一个PK +)每列一个。

将子表中的行组合成一个5NF行很容易,我可以查看(但不要通过视图更新,通过事务存储过程直接对每个子表执行此操作)。

更多,更小的表,是规范化关系数据库的本质。习惯它。由于缺乏规范化,重复和无效,更少,更大的表更慢。在SQL中加入很麻烦&lt;但这就是我们所拥有的一切。连接本身没有成本,只有连接的表(行,行宽,连接列,数据类型,不匹配,索引[或不])。数据库针对规范化表进行了优化,而不是针对数据堆。和大量的表格。

这恰好是最佳表现,毫不奇怪。有两个原因:

  1. 表格较窄,因此每页有更多行,每个物理I / O可获得更多行,同一缓存空间中有更多行。

  2. 由于你没有Null,这些列是固定的len,没有解压缩来提取列的内容。

  3. 对于具有许多可选(空)列的大型表,没有优点,只有缺点。从来没有人违反标准。

    无论您是考虑4个还是400个新表,答案都不会改变。

    • 如果您正在认真考虑许多表格,那么一个建议是:您正朝着第六范式的方向前进,却没有意识到这一点。所以要实现它,并正式这样做。 400表将更好地控制。如果你有专业人士去做,他们会将其标准化,并最终回到不到100个。

答案 1 :(得分:2)

我是一名SQL服务器DBA,因此我将建议我在SQL Server 2008中做些什么。

将列添加到现有表中为nullable,将列标记为SPARSE。使用稀疏标记不会增加现有表页中额外列的存储空间,并且仍允许您将稀疏列作为列进行查询。 SQL Server在内部以XML格式存储稀疏列,也可以查询或显示它们。

如果有遗留应用程序无法处理新的表结构

  1. 重命名表格
  2. 使用原始表结构创建视图,并将其命名为原始表名称
  3. 如果您的版本不支持稀疏列,则为现有表构建一个子表,将子表与父表的ID链接到父表。在两个表中创建一个视图以显示数据。

答案 2 :(得分:0)

您的查询是否更有可能需要将(XX,1)设置的行与(YY,2)设置等组合起来......?

如果没有,那么拆分成单独的表会更快,因为用于所有查询的各个表都比较窄。

如果你将它们组合起来,它们可能会稍微慢一些,因为你需要UNIONs,这需要对主表进行重复查询。

答案 3 :(得分:0)

我同意DVK的意见,如果你选择(B),你最终将不得不查询几个表来获得所有原始的Field1值,更不用说JOINs等的复杂性。除非分成单独的表也对应于分离成不同的实体。

我同意保罗的意见,因为如果不了解所涉及的实体的详细信息以及您将要运行的各种查询和更新,您的问题就无法真正得到解答。

答案 4 :(得分:0)

我记得以前有这些疑惑。

从数据验证的角度来看,选项(B)更有利。您可以更好地对字段设置约束。这正是您希望将users表拆分为studentsteachers等以强制执行NOT NULL约束的原因,具体取决于用户的角色。

通常,由于索引问题,在表中包含大量NULL值会对性能造成影响。

根据经验,只要联接中涉及的表数量为4或更少,您就不必担心性能损失。

编辑:如果您担心数据库中的表格数量,建议您查看here