12

我需要将其他数据放入数据库中,并且可以选择修改现有表 (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)可能会更好。


编辑1

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

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

我试图了解拥有一个包含许多未使用值的大表与将相同的数据拆分到更多数量的表中是否有利弊。更多的表是否会导致数据库性能下降(我们已经有大约 80 个表)?

4

5 回答 5

19

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

好吧,什么是正确的,最佳实践等,称为规范化。如果您正确执行此操作,则不会有可选列(不是字段),也不会出现 Null。可选列将位于单独的表中,行数较少。当然,您可以排列表格,使它们成为一组可选列,而不是(一个 PK 加)每个列。

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

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

这恰好是最佳的再性能,不足为奇。有两个原因:

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

  2. 由于您没有 Null,因此这些列是固定的 len,无需拆包以提取列的内容。

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

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

  • 如果您正在认真考虑这么多表格,那么一个建议是:您正朝着第六范式的方向前进,而没有意识到这一点。所以意识到这一点,并正式这样做。400张桌子将得到更好的控制。如果你让专业人士来做,他们会正常化,最终回到不到 100。
于 2010-11-27T06:01:20.483 回答
2

我是一名 SQL Server DBA,所以我会建议我在 SQL Server 2008 中会做什么。

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

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

  1. 重命名表
  2. 创建具有原始表结构的视图并将其命名为原始表名

如果您的版本不支持稀疏列,则为现有表构建一个子表,将子表链接到具有父表 ID 的父表。创建跨两个表的视图以显示数据。

于 2010-11-28T15:31:49.770 回答
0

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

如果不是,那么拆分成单独的表会更快,因为用于所有查询的单个表更窄。

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

于 2010-11-26T15:59:42.927 回答
0

我同意 DVK 的观点,如果您选择 (B),您最终将不得不查询多个表以获取所有原始 Field1 值,更不用说 JOIN 的复杂性等。除非拆分成单独的表,否则这没有意义对应于分离成不同的实体。

我同意 Paul 的观点,如果不知道所涉及实体的详细信息以及您将运行的查询和更新的种类,您的问题就无法真正得到回答。

于 2010-11-26T16:13:32.157 回答
0

我记得以前有这些疑问。

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

通常,由于索引问题,表中有很多 NULL 值对性能不利。

根据经验,只要连接中涉及的表数为 4 个或更少,您就不必担心性能下降。

编辑:如果您担心数据库中的表数量,我建议您看这里

于 2010-11-26T18:46:46.283 回答