什么是DBMS中的原子性?

12
我在关于数据库管理系统的第一范式(1NF)中读到了以下内容:
其中有这样一句话:
“每个列应该是原子性的。”
请问有人可以举例详细解释一下吗?
4个回答

9

关于"原子性"

在Codd最初的1969年和1970年的论文中,他将关系定义为每行都有一个属性值。该值可以是任何东西,包括一个关系。这没有使用"原子性"的概念。他解释说,"原子性"意味着非关系值(即非表值):

到目前为止,我们已经讨论了在简单域上定义的关系示例——元素为原子(不可分解)值的域。在关系框架内可以讨论非原子值。因此,某些域可能具有关系作为元素。

他在口头表述中使用了"简单"、"原子"和"不可分解"等词汇。他理解关系具有行,每列都有一个相关联的名称和值;按定义,属性是"单值"的;该值可以是任何类型。在关系上唯一重要的结构属性是成为关系。它也只是一个值,但您可以通过关系查询它。然后他使用"非简单"等词汇来表示关系值。

在Codd的1990年著作《数据库管理的关系模型:版本2》中,从数据库角度来看,数据可以分为两种类型:原子和复合。DBMS(不包括某些特殊功能)无法将原子数据分解为更小的部分。由结构化组合的原子数据组成的复合数据可以被DBMS分解。在关系模型中,只有一种类型的复合数据:关系。每个关系定义的域中的值需要在DBMS方面是原子的。关系数据库是各种程度关系的集合。所有查询和操作运算符都在关系上,它们都生成关系作为结果。为什么只关注一种类型的复合数据?主要原因是任何额外的复合数据类型都会增加复杂性而不增加功率。“在关系模型中,只有一种类型的复合数据:关系。” 很遗憾,“原子=非关系”不是你将要听到的内容。(不幸的是,Codd并不是最清晰的作者,他的解释性言论常常与他的底线混淆。)实际上,关系模型的几乎所有演示都没有超越Codd仅仅作为一个跳板的地步。它们推广了一个不太有用、混乱模糊的概念,被规范化为“原子”,决定了“规范化”。有时候他们错误地使用它来定义关系。而Codd则使用日常的“非原子”来引入定义关系的“非原子”作为关系值,并将“规范化”定义为无关系值域。
(“不是重复组”作为“原子”也没有帮助,因为它定义为不是甚至不是一个关系概念。1970年,Codd说,“在当前数据库术语中,属性和重复组这些术语大致相当于简单域和非简单域。”)
例如:这种误解长期以来一直由Chris Date提倡,他是早期关系解释者和传教士中值得尊敬的人物,主要在他的开创性的仍然流行的书《数据库系统简介》中。现在(2004年第8版),它幸运地呈现了一个有帮助的关系导向的扩展概念,区分关系、行和“标量”(非关系非行)域。
这个定义仅说明所有[关系变量]都在第一范式中。 例如:Maiers的经典著作《关系数据库理论(1983)》: 定义原子性并不明确;一个在一个应用程序中是原子的值,在另一个应用程序中可能是非原子的。一般的准则是,如果应用程序只处理值的一部分,则该值是非原子的。 例如:当前维基百科关于第一范式(正常形式)中原子性部分的文章实际上引用了上面的介绍部分。然后忽略了精确的含义。(然后它说一些关于非原子乌龟何时停止的话,难以理解。)
Codd指出,“每个关系定义的域中的值都需要在DBMS方面是原子性的。” Codd将原子值定义为“不能被DBMS分解成更小的部分(除了某些特殊函数)”,这意味着一个字段不应该被分成具有多种数据的部分,以至于同一字段的另一部分对于DBMS的含义取决于该字段的另一部分。
关于“规范化”和“1NF”:
当Codd在1970年使用“规范化”一词时,他的意思是从关系数据库中消除关系值(“非简单”)域:
“由于这个原因(和其他原因,将在下面提到),消除非简单域的可能性似乎值得研究。实际上,有一个非常简单的消除过程,我们称之为规范化。”
自从Codd最初的规范化论文以来,规范化理论始终给出了与所有关系相关的结果,而不仅仅是Codd的第一范式中的那些。因此,人们可以按照最初的意义进行“规范化”,即从仅具有关系的状态转变为没有关系值列的“规范化”的“第一范式”。同时,在忽略域是否为关系的情况下,人们也可以按照规范化理论的意义,将一个仅具有关系的“第一范式”转换为更高级别的规范形式。此外,“规范化”通常还用于消除具有“部分”的值的含糊概念。“规范化”也被错误地用于设计非关系数据库的关系版本(无论是仅具有关系还是其他某种“第一范式”的意义)。
关系型数据库的精神在于避免具有相同含义的多个列或具有有趣部分的域,而是选择另一个基础表。但我们必须始终对何时停止表示部分并仅将列视为“原子”(非关系值)或“非原子”(关系值)做出非正式的人体工程学决策。

数据库管理系统中的规范化


8

原子性和第一范式...这不是关于原子事务,而是关于定义和列内容。

"原子"意味着“不能被分割或分成更小的部分”。应用于第一范式,这意味着一列不应包含多个值。它不应组合或结合具有自己意义的值。

这通常涉及到数据库设计人员经常犯的两个常见错误:

1. 一个列中有多个值(列表列)

包含一系列值的列,通常是空格或逗号分隔的,例如此博客文章表:

id title     date_posted content tags
1  new idea  2014-05-23  ...     tag1,tag2,tag3
2  why this? 2014-05-24  ...     tag2,tag5
3  towel day 2014-05-26  ...     tag42

或者这个联系人表格:
id room phones
4  432  111-111-111 222-222-222 
5  456  999-999-999
6  512  888-888-8888 333-3333-3333

这种非规范化类型很少见,因为大多数数据库设计者认为这不是一件好事。但确实有像这样的表存在。它们通常来自于对数据库的修改,可能看起来更简单的方法是扩展列并将其用于存储多个值,而不是添加一个规范化相关表(这经常会破坏现有应用程序)。
2. 复杂的多部分列
在这种情况下,一个列包含不同的信息位,可以设计成一组单独的列。
典型的例子是fullname和地址列:
id fullname              address
1  Mark Tomers           56 Tomato Road
2  Fred Askalong         3277 Hadley Drive
3  May Anne Brice        225 Century Avenue - apartment 43/a

这些非规范化类型很常见,因为很难划分什么是原子的和什么不是。根据应用程序,多部分列在某些情况下可能是最佳解决方案。它的结构较少,但更简单。
将地址分解为许多原子列可能意味着需要更复杂的代码来处理输出结果。另一个复杂性来自于结构不能适应所有类型的地址。使用一个单一的VARCHAR列不会出现这个问题,但可能会出现其他问题...通常涉及搜索和排序。
多部分列的极端情况是日期和时间。大多数关系型数据库管理系统提供日期和时间数据类型,并提供处理日期和时间代数以及提取各种位(月份、小时等)的函数。很少有人会认为在关系型数据库中拥有单独的年、月、日列是方便的。但我见过这样的情况...而且有很好的理由:这是司法部门数据库中出生日期的用例。他们必须处理许多没有或几乎没有文件的移民。有时你只知道一个人出生于某一年,但你不知道出生的日子或月份。你无法用一个单一的日期列来处理这种类型的信息。

回复不错,但姓名/地址的示例至少有问题。将姓名分解为名/中间名/姓,或将地址分解为国家/州/邮政编码/路名/门牌号只有有限的用途,并需要国际用户适应您的方案。 - peterchen
1
我认为我已经清楚地表明,在许多情况下,这种非规范化可以被接受,具体取决于应用程序和用户要求。不过,我会努力让它更清楚明白。 - Frazz
4
这些类型的非规范化很常见,... 这并不是非规范化。 - Mike Sherrill 'Cat Recall'

3
每一列都应该是原子的。Chris Date说:“请注意,合法值不仅仅是像整数3这样的简单值。相反,值可以任意复杂;例如,一个值可能是一个几何点、多边形、X射线、XML文档、指纹、数组、栈、列表或关系(等等)。"他还说:"如果在该relvar的每个合法值中,每个元组恰好包含每个属性的一个值,则该relvar在1NF中。"他通常不鼓励使用“原子”这个词,因为它有混淆的内涵。 "单一值"可能是一个更好的术语。例如,像“2014-01-01”这样的日期就是一个单一的值。它不是不可分割的;相反,它很明显是可以分割的。但是dbms对于具有部分的单个值会执行以下两种操作之一:dbms将这些值作为整体返回,或者dbms提供函数来操作这些部分。(客户端不必编写代码来操作这些部分。)在日期的情况下,SQL可以返回日期的全部(SELECT CURRENT_DATE),返回一个或多个日期的部分(EXTRACT(YEAR FROM CURRENT_DATE)),添加和减去间隔(CURRENT_DATE + INTERVAL '1' DAY),从另一个日期中减去一个日期(CURRENT_DATE - DATE '2014-01-01'),等等。在这个(狭窄的)方面,SQL是相当关系型的。

0

在ACID中,那是完全没问题的。 - Patrick Hofman
@Rohaan - 这只是一种1NF技术。 - Pramod S. Nikam
@pramod.nikam.dev - 是的,但他正在询问含义。 - RobertKing

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接