数据库模式的适度指南


Mookiezoolook的“花的几何形状”

对于要根据流量和复杂性进行缩放的应用程序,最初设计一个称职的数据库方案非常重要。如果您做出错误的选择,则必须花费很多精力,以使此错误的模板不会传播到服务和后端控制器,最后也不会传播到前端。

但是,如何评估哪个电路更好呢?当我们谈论数据库体系结构时,“更好”是什么意思? Mail.ru云解决方案团队邀请您遵循软件开发顾问 Mike Alcha的建议。在我们看来,他相当简洁地总结了主管架构的一些原则。


主任:我认为我们应该建立一个SQL数据库开发人员(他甚至了解他在说什么,还是只是在商业杂志上看到了某种广告?..):您想要数据库什么颜色?”。导演:也许丁香拥有最多的记忆





一些基本技巧


因此,努力做到两点很重要

  1. 将信息分成表时,将存储所有信息。
  2. 存储的冗余很小。

关于第二点:我们是否仅由于存储大小问题而希望减少冗余?不,我们这样做主要是因为如果您在更新过程中未更新表示相同信息的所有字段,则冗余数据的存在会导致不一致问题

以下是一些指南,可帮助您更好地了解良好的体系结构

  1. 至少使用第三种标准格式(根据Bill Kent 的措辞其中每个非密钥属性“必须提供有关密钥,完整密钥的信息,除了密钥之外的任何信息” )。
  2. 以限制形式创建最后一道防线。
  3. 切勿将整个地址存储在一个字段中。
  4. 切勿在一个字段中存储名字和姓氏。
  5. 设置表和字段名称的约定并坚持使用。


- 你在做什么?

优化此SQL查询。” 它放慢了速度,用户开始抱怨。

- 为了优化需要注释中的淫秽语言 - 如果您看到原始代码,则不会询问。 让我们更详细地考虑这些建议。





1.至少使用第三范式


数据库体系结构可以分为以下几类:

  • 第一个范式。
  • 第二范式。
  • 第三范式。
  • 博伊斯·科德的正常形式。

这些类别按质量表示分类。我们将简要回顾所有类别,并查看为什么至少需要第三个范式。

第一范式


对于第一个范式,数据库中每个表的每个列的每个值必须是原子的。原子是什么意思?简而言之,原子值是“单件事情”。

例如,我们有一个这样的表:
名字年龄地区
母鹿27{“网站设计”,“客户研究”}
玛丽33{“长期战略规划”,“招聘”}
汤姆史密斯35{“营销”}

在这里,Areas包含的不是原子的值。例如,在John Doe行中,该字段存储两个实体:网站设计和客户研究。

因此,该表不是第一个普通形式。

为使其具有这种形式,每个字段中仅应存储一个值

第二范式


在第二范式中,不能从主键的较小部分派生不属于主键的列(或可以充当另一个主键的一部分)的列

这是什么意思?

假设您具有这样的基本架构(我在此表中强调了与主键相对应的字段):
员工IDproject_id小时员工姓名项目名称
1个1个10约翰“网站设计”
21个二十玛丽“网站设计”

在此项目中,可以直接从employee_id推断出雇员姓名,因为这样的想法是,雇员姓名由其标识符唯一确定。

同样,项目名称由project_id标识符唯一标识。

因此,我们有两列可以从主键部分推导出。

这些示例中的每个示例都足以使该表脱离第二范式。

另一个结论是,如果表采用第一种标准格式,并且所有主键均为单列,则该表已经采用第二种标准格式。

第三范式


为了使表与第三范式相对应,它必须为第二范式,而表中不应有任何属性(列),但主属性除外,这些属性可传递地依赖于主键。

这是什么意思?

假设您具有以下架构(远非理想):
员工姓名员工ID年龄部门编号部门名称
约翰1个27123“营销”
玛丽233456“操作”
汤姆335123“营销”

在此表中,department_number可以从employee_id推断,department_name可以从department_number推断。因此,department_name可传递地依赖于employee_id!

如果存在这样的传递依赖项:employee_id→department_number→department_name,则该表不是第三种正常形式。

因此出现什么问题

如果可以从部门编号中得出部门名称,则为每个员工存储此字段会导致过多的冗余。

想象一下,营销部门将其名称更改为“ Marketing and Sales”。为了保持一致性,您将不得不为该部门中的每个员工更新表格每一行中的单元格!在第三范式中,这不会发生。

此外,如果玛丽决定离开公司,将会发生以下情况:我们必须从表中删除她的行,但是如果她是运营部门中的唯一雇员,那么该部门也将被删除。

所有这些问题都可以通过第三种正常形式完全避免。


妈妈的功绩她女儿的名字叫Help!我被迫假护照

2.以限制形式创建最后一道防线


您正在使用的数据库不仅仅是一组表。内置某些功能。其中许多功能可帮助确保数据质量和准确性。

限制设置了规则,可以在数据库字段中输入什么值。

在数据库中定义关系时,请确保设置外键约束。

确保指定在删除和更新与其他表中的其他行关联的行时应执行的操作(ON DELETE和ON UPDATE规则)。

确保对绝不应该为空的所有字段使用NOT NULL。在后端设置检查可能很有意义,但请记住,崩溃总是会发生,因此添加这种限制不会有任何危害。

设置CHECK检查限制以确保表格值在可接受的范围内,例如,产品价格始终为正值。

一个有趣的事实:在2020年4月,正是这样的软件限制阻止了莫斯科MICEX的交易,因为WTI石油期货的价格跌至零以下。与莫斯科证券交易所不同,纽约商品交易所NYMEX 在事件发生前一周更新了该软件,因此它能够成功以负价进行交易,即向卖方收取的买方附加费-大约为255美元。反式

所有PostgreSQL限制都可以在这里找到

3.切勿将整个地址存储在一个字段中


如果您的应用程序或网站的表单中只有一个字段,用户可以在其中输入其地址,那么它的味道就不好了。在这种情况下,很有可能在数据库中还将有一个字段将地址存储为简单字符串。

但是,如果您需要按城市组合客户购买量以查看哪个城市更受欢迎,该怎么办?你可以做到吗?

这将非常困难!

由于完整地址以字符串形式存储在数据库字段中,因此您首先必须确定该字符串中有多少是城市!考虑到该字段中所有可能的地址格式,这几乎是不可能完成的任务。

因此,请确保将通用的“地址”字段分解为特定的字段:街道,门牌号,城市,地区,邮政编码等。

另一个地址问题-匿名字段


这是Michaels Blach的著作《提高软件质量的铜弹》中的插图:


在这里可以看到哪些潜在问题?您可以轻松地将芝加哥市与芝加哥街道区分开吗?可能不是。

因此,请记住始终为每个信息单元提供明确的列名。


如何写简历

- 您有SQL经验吗?

- 不(不)

- 写:NoSQL专家。

4.切勿在一个字段中存储名字和姓氏


与地址的情况类似:姓名和姓氏的变体数量太大,无法清楚地区分。

当然,如果名称和姓氏之间有空格,则可以将其与姓氏分开。

例如,“ Mike Alche”→名称“ Mike”和姓“ Alche”。

但是,如果用户输入中间名怎么办?还是他有双重姓氏?但是,如果有中间名和双姓怎么办?

如何确定名称和拆分字符串的姓氏在哪里?错误是不可避免的。

避免许多问题的一种方法是为first_name和last_name用户名创建单独的字段(以表单形式)。这样,您就可以允许用户共享自己的名称,并可以以一致的方式存储数据。

注意:我并不是说数据库字段中禁止使用空格。例如,对于Juan Juan Del Potro之类的名称,Juan Martin的第一部分在first_name字段中,而Del Potro在last_name字段中。当然,这并不完美您可以选择具有Middle_name和second_last_name列。查看更多有关在列表中的“姓氏和名字的可能的变化有关名称程序员的误解 ”和文章“ 关于名程序员的误解-举例 ”。您必须在准确性和实用性之间达成某种折衷方案。

5.设置表和字段名称的约定并坚持使用


使用看起来像user.firstName,user.lst_name,user.birthDate等数据的数据很烦人。

我建议您建立下划线命名规则,因为并非所有SQL引擎都以相同的方式处理大写字母,并且用引号将所有内容括起来非常繁琐。

选择与调用表相同的形式-复数形式或单数形式(例如,复数形式的用户或单数形式的用户)。我更喜欢单数,但是默认情况下,所有后端框架似乎都是复数的。您必须遵循模式并使用复数。

还有什么要读的

  1. 为项目选择什么数据库,这样就不必再次选择
  2. IIoT-: Mail.ru Cloud Solutions .
  3. .

All Articles