数据规范化和写入查询

| 我是小。开发人员(工作5个月),我对数据规范化有疑问。现在,据我所知,数据标准化背后的一般原理是创建一个RDBMS,其中将数据冗余降至最低。在我的项目中,一名数据库人员创建了一个数据库。我们有50多个表,并且数据库中的表通常非常分散,即。一个表有两三列,仅此而已。现在,在编写sql查询时,这已经成为一个小麻烦了,因为每个查询都涉及梳理几个不同的表并将它们连接在一起。我想知道这是否是数据标准化的副作用?还是这指向别的东西? 我知道,对我而言,最简单的方法是根据必须编写的查询来编写表。这将创建一个包含大量冗余数据的数据库,但是我很好奇是否有一个令人满意的介质吗? 就像一个后记一样,我不想像我抱怨自己的作品那样碰面,但是我真的很想了解更多有关此的信息。我的工作环境不是最友好的,所以我不愿意与同事一起提出这个问题。但是,我将不胜感激经验丰富的人的任何想法,书籍,教程或意见。 谢谢。     
已邀请:
           数据规范化背后的一般原则是创建一个RDBMS,其中将数据冗余降至最低。 仅部分正确。 规范化与“冗余”无关。 关于“更新异常”。 1NF是“请勿使用数组”规则。破坏1NF意味着行不是原子的,但是集合和集合中的独立更新效果不佳。会有锁定和缓慢。 2NF是“一键”规则。每行只有一个键,并且行中的所有内容都取决于该键。密钥的一部分没有依赖性。有些人喜欢谈论候选键,自然键和外键。它们可能存在,也可能不存在。当所有属性都取决于一个键时,将满足2NF。如果密钥是单列代理密钥,则可以轻松满足此标准格式。 如果违反了2NF,则您的列取决于键的一部分,而不是整个键。如果您有一个以(零件号,修订号)为键的表,并且具有颜色和重量的属性,则重量取决于整个键,而颜色仅取决于零件号。您遇到2NF问题,可以更新某些零件颜色,而不能更新其他零件颜色,从而导致数据异常。 3NF是“唯一密钥”规则。如果将派生数据放在一行中,然后更改派生结果,则它与源列不匹配。如果在不更新派生值的情况下更改了源列,那么也会遇到问题。是的,触发器是允许3NF设计违规的错误解决方法。那不是重点。重点仅仅是定义3NF并表明它可以防止更新问题。   每个查询都涉及梳理几个不同的表并将它们连接在一起。我想知道这是否是数据标准化的副作用? 它是。     
现在,据我了解,一般   数据标准化背后的原理是   创建一个RDBMS,其中数据   冗余度保持最小。 嗯好   在我的项目中,一位数据库人员   创建了一个数据库。我们有50多个桌子,并且   数据库中的表通常非常   零散的一个表有两个或   三栏,就是这样。 表的数量没有说明设计的好坏。一些企业需要一两个。其他人需要更多。我曾在财富500强企业中开发过具有数千张表的数据库。 列数没有说明设计的好坏。列数与碎片无关。我会说列数相对较少的表通常是一个好兆头。并非总是一个好兆头,但通常是一个好兆头。   现在,当涉及到编写SQL   查询,它已经成为一种   小麻烦,因为每个查询都涉及   通过几个不同的梳理   表并将它们连接在一起。一世   想知道这是否是一面   数据标准化的影响?还是   这指向别的东西吗? 有两个不同的共同原因。 规范化表时,通过标识功能依赖性,隔离一个或多个新表中的功能相关列并将其从原始表中删除,可以减少冗余(并提高数据完整性)。因此,从低范式转换为高范式的意义上是规范化表格 总是增加 桌子 总是减少列数 在原始表格中,以及 有时需要联接才能检索 人类的数据。 另一种常见的做法是用ID号替换字符串。这与规范化无关。 (没有\“ id number normal form \”之类的东西。)用id号替换字符串 总是增加 桌子 不会更改列数 在原始表格中(除非在 与标准化同时进行), 始终需要联接才能检索人类数据。 这个线程的其他部分似乎有些混乱。我意识到,严格来说,以下内容均与OP的问题没有直接关系。 1NF是“一个值”的原则。它与“原子”行无关。在关系模型中,原子不指行。它指的是价值。 \“一个值\”表示行和列的每个交集都包含一个值。 (换句话说,该值是\“ atomic \”。但是atomic这个词有一些不幸的含义,因此大多数现代从业者都避免使用它。)它可以任意复杂。但是,如果它具有本身具有含义的部分,则dbms要么完全忽略这些部分,要么提供操作它们的功能。 (您不必编写函数来操纵部件。) 我认为最简单的例子是约会。日期由年,月和日组成。 dbms要么忽略那些部分(如
SELECT CURRENT_DATE
),要么提供操作它们的功能(如
SELECT EXTRACT(YEAR FROM CURRENT_DATE)
)。 企图避开“一个价值”原则会导致一个必然结果:“没有重复的群体”原则。 重复组涉及一个域中的多个值,所有值都具有相同的含义。因此,下面的表格是一种重复组的示例。 (还有其他种类。)\“ phone_1 \”和\“ phone_2 \”的值来自同一域,并且它们的含义相同-用户\'n \'具有电话号码(phone_1和phone_2)。 (主键为\“ user_id \”。)
user_id    phone_1           phone_2    
1          (111) 222-3333    (111) 222-3334
2          (111) 222-3335    (111) 222-3336
但是下一张表虽然很相似,但是没有重复的组。这些值来自相同的域,但含义不同。 (主键为\“ user_id \”。)
user_id    home_phone        work_phone    
3          (111) 222-3333    (111) 222-3334
4          (111) 222-3335    (111) 222-3336
2NF是“整个密钥”的原则。它与键的数量无关。具有\'n \'列的表可以具有\'n \'键。 (例如,请参见另一个SO答案。)在关系模型中(以及扩展,当您进行标准化练习时),如果您看到单词key本身,请考虑“ candidate key”。 相反,2NF与具有多列的候选键有关。当候选键具有多个列时,2NF要求每个非素数属性在功能上均取决于每个候选键的所有列,而不仅取决于任何候选键的某些列。 (非素数属性是不属于任何候选键的属性。) 下面的示例改编自2nf上的Wikipedia条目。 (主键是{employee,skill}。)
Table: employee_skills
employee        skill            current_work_location
--
Jones           Typing           114 Main Street
Jones           Shorthand        114 Main Street
Jones           Whittling        114 Main Street
Bravo           Light Cleaning   73 Industrial Way
Ellis           Alchemy          73 Industrial Way
Ellis           Flying           73 Industrial Way
Harrison        Light Cleaning   73 Industrial Way
虽然非主列current_work_location在功能上确实依赖于主键{employee,skill},但在功能上也仅依赖于主键\“ employee \”的一部分。该表不在2NF中。 您不能通过为每行分配一个代理密钥来规避2NF问题。 (主键是es_id;以前的主键{employee,skill}有一个UNIQUE约束)。
Table: employee_skills
es_id   employee        skill            current_work_location
--
1       Jones           Typing           114 Main Street
2       Jones           Shorthand        114 Main Street
3       Jones           Whittling        114 Main Street
4       Bravo           Light Cleaning   73 Industrial Way
5       Ellis           Alchemy          73 Industrial Way
6       Ellis           Flying           73 Industrial Way
7       Harrison        Light Cleaning   73 Industrial Way
很明显,添加id号并不能消除部分依赖性
employee->current_work_location
。在不删除部分依赖性的情况下,该表仍不在2NF中。 3NF是“无传递依赖项”原则。正如您可以从Wikipedia示例中看出来的那样,它不一定与派生或计算的数据有关。 (主键为{tournament,year}。此表不在3NF中。)
Table: tournament_winners
tournament             year  winner            winner_date_of_birth
--
Indiana Invitational   1998  Al Fredrickson    21 July 1975
Cleveland Open         1999  Bob Albertson     28 September 1968
Des Moines Masters     1999  Al Fredrickson    21 July 1975
Indiana Invitational   1999  Chip Masterson    14 March 1977
两个依赖关系表明此表具有传递依赖关系。 优胜者出生日期中的值 似乎在功能上取决于 首要的关键。每个主键值 确定一个且只有一个值 获奖者的出生日期。但是。 。 。 优胜者出生日期中的值 也似乎在功能上依赖于 优胜者。每个赢家的价值 确定一个且只有一个值 获奖者的出生日期。 鉴于这两个明显的功能依赖性以及对比赛,获胜者和生日的含义的理解,我们可以说 获胜者-> winner_date_of_birth是一个 功能依赖性,以及 {比赛,年份}->获胜者是一种功能依赖性,并且 {比赛,年份}-> winner_date_of_birth是可传递的 依赖性。     
在这种困境中,数据库视图是至关重要的工具。这个出色的介绍说:   这是个好消息:您不必使用规范化表! ……(至少对于DBA而言)在标准化数据表之上创建连接视图的抽象层是非常容易的,将基本表完全“置于幕后”并且不可见。     
        听起来像是数据规范化,但我必须更多地了解架构,业务案例等,才能可靠地进行该调用。如果可以控制数据库,则可以编写一个视图,该视图表示链接表的常见查询。为了提高性能,可以创建索引视图或实例化视图(名称取决于数据库平台,在这种情况下,取决于Oracle vs. Sql Server)。 几乎所有数据库入门都将帮助您理解这些概念。如果您正在使用Sql Server,并且对学习更多感兴趣,那么SQL Server联机丛书是一个很好的资源。     
        拥有大量表绝对是规范化数据库设计的一个征兆。这在编写查询时可能会很痛苦,但是比使数据不同步要好得多。 有时我会写一些从具有数千个表的数据库运行的报告。每天晚上,我们都有一个程序,该程序运行并将生产表中的数据转储到数据仓库中,以便我们可以更轻松地对其进行报告。数据仓库表的标准化要少得多,这使得编写查询要简单得多。如果在您的情况下有意义,您可能需要考虑采用这种方法。     
        如果不查看数据,很难说您的数据是否被过度规范化(或者只是未正确规范化-将字段分布在多个表上并不意味着已被规范化)通常来说,您可能必须加入几个表,以查看规范化的数据库中的有用数据。 您可以创建将表连接在一起的视图,然后可以查询视图。这在选择数据时可能会有所帮助。     
        在设计良好的数据库中,您在查询中需要的联接应该很容易编写代码。缺点是您有冗长的SQL。好处是巨大的: 一致的易于更新表。 根据业务需要快速更改。设计良好的数据库通常可以处理原始设计中甚至没有想到的查询。 快速容纳新实体。向设计良好的数据库添加新的数据实体和属性相对容易。将看似简单的更改合并到非规范化数据库中可能是一场噩梦。     

要回复问题请先登录注册