在表中维护3个小列或1个大列是否更好?

时间:2012-04-26 11:47:24

标签: database oracle

三个小数字列[Number(1)]>>

OptionA | 0/1
OptionB | 0/1
OptionC | 0/1

或一个较大的字符串列[Varchar2(29)]>>

Options | OptionA=0/1|OptionB=0/1|OptionC=0/1

我不确定数据库处理表的方式,但我认为将三列保存为Number(1)比将一列保存为Varchar2(29)更好!

- 编辑 -

让我再解释一下情况:

我正在研究一个通用框架,其中跟踪所有传入/传出请求/响应,这些交互可以被引导到DB / File / JMS;现在所有的配置都是从一个表中加载的,该表有一个对应于输出类型的列,目前我正在使用“DB = 1 | FILE = 1 | JMS = 0”作为该列的值,以便以后如果任何人都希望为他们的模块添加这个,他们可以很容易地理解发生了什么,在我的代码中,我写了一个简单的逻辑,用“|”拆分字符串然后我使用独占或操作符在开关盒之间切换选择..

一切都已经完成但是我不喜欢一个大列的想法比三个小+更好它会删除我正在做的分裂字符串。

- 编辑 -

我终于澄清了,可能有一种情况我们必须添加更多选项;在这种情况下,如果我们按列添加数据,它将导致修改表+更改实体+如果是全部则添加更多;另一方面,我最终用一个简单的逻辑逻辑在一个枚举之间切换,以便在选项之间切换;这样,我需要修改enum&为新选项&添加新的处理程序那我们很高兴。

3 个答案:

答案 0 :(得分:4)

使用单个列存储多个数据可能是您在数据库中可以做的最糟糕的事情。

违反第一范式至少有以下缺点:

  1. 更难查询。 OptionA = 1 and OptionB = 1 and OptionC = 0substr(options, 9, 1) = '1' and substr(options, 19, 1) = '1' and substr(options, 19, 1) = '0'
  2. 不太灵活。当您需要添加其他选项时会发生什么?添加新列很容易。添加新格式可能会破坏旧查询。例如,如果有人尝试使用substr(options, -1, 1)阅读OptionC。 (虽然这是使用第三个选项的一个很好的理由 - 一个单独的表。)
  3. 没有类型安全。这可能是一个非常微妙和棘手的问题。假设你写substr(options, 9, 1) = 1而不是substr(options, 9, 1) = '1'。如果有人得到格式错误,单个值可能会破坏大量查询。或者更糟糕的是,它只会间歇性地崩溃少量查询,因为访问路径不断变化。 (虽然您可以通过检查约束来防止这种情况。)
  4. 查询速度较慢。通常,表达式或条件中完成的工作量不是查询的重要成本。但是添加大量不必要的字符串操作可能会有所不同。
  5. 优化程度较低。 Oracle只有在能够理解您的数据时才能构建高效的查询计划。例如,假设OptionA在99.9%的时间内为“0”。过滤OptionA = 0时,Oracle可以使用直方图对返回的行数进行非常准确的预测。但是对于substr(options, 9, 1) = '1',你只会得到一个疯狂的猜测。如果您使用此列进行复杂查询,则可能会花费大量时间尝试“修复”基数估算值。 (虽然表达式统计可能有助于此吗?)
  6. 有时候非规范化是一个好主意。例如,如果您有数TB的数据并压缩表,则单个列可能占用更少的空间。 (但如果你想节省空间,为什么不使用像“000”这样的格式?)。

    如果真的有充分的理由,那肯定需要记录下来。也许在专栏上添加评论。

答案 1 :(得分:1)

首先,如果我正确地阅读您的问题,您希望每个选项都只有两个可能值中的一个,对吗?

如果是,那么你可以:

  • 为每个选项
  • 都有一个单独的整数(或布尔)列
  • 有一个options列,其中包含1和0的字符串,每个选项一位数,例如“001”
  • 使用一个整数的'options'列,并为每个选项使用位值,例如optionA == options& 1,optionB == options& 2等。
  • 某些数据库具有您可以使用的位向量数据类型。对于mysql,有BIT数据类型,可以存储长达64位的位串。

每种方法都需要在代码复杂性和效率之间进行权衡。问问自己,通过采用这些选项,可以节省多少机器的时间或存储空间? 你的时间将保存多少?

答案 2 :(得分:1)

在这种情况下,3列方法是我推荐的方法,不仅在提取数据方面保持简单,而且您是否希望可以针对所有3列设置值,而不是仅限于一个VarChar2领域。如果你选择单列VarChar2,那么使用substr命令或者另一种变体提取你需要的信息是相当简单的,虽然这对Oracle数据库来说不是很重要,但它确实在服务器上增加了额外的工作量。这不是必要的。