如您的帖子所述,如果打算创建一个关系数据库(为简便起见,请使用RDB),因此,希望它能正常运行,那么简短的答案是:
主要目标应该是按原样管理相关数据,这是非常有价值的组织资产,并且要实现该目标的可靠方法是采用可靠理论支持的技术手段。
因此,作为数据库专业人员,您可以利用EF Codd博士提供的最新和优雅的关系模型机制来实施业务规则,并避免如果不加以利用最终会出现的问题。
在这方面,我将分享(a)我的总体约束,以及(b)关于数据库事务状态和所讨论的工作环境的以下几点考虑。
外键约束,数据关系和参照完整性
RDB必须高精度地反映感兴趣的业务环境的特征,这绝对需要由遵循最佳实践的建模者或设计者领导的深入概念级分析,并依靠业务专家的不可或缺的协助。该分析必须正确识别并制定适用的业务规则。
因此,如果这样的建模者已经确定相关数据之间存在相互关系,则他或她必须配置相应的逻辑级别限制,以便数据库管理系统(DBMS)可以保证数据与确切特征保持一致,并且始终在上述分析中确定的规则。
关于正在讨论的数据库,可以推断出已经确定了相关的相互关系,因为您提到存在一种程序化的(并且容易规避的)尝试,通过使用应用程序代码(在数据库管理系统之外)来强制执行它们。是一种关系前的方法),在任何情况下都必须“触摸”数据库以尝试验证所述相互关系的完整性。
但是,正如您所知,这并不是保护参照完整性的最佳技术,因为关系科学为此目的规定了一种非常强大的工具,即外键(FK)约束。这些约束很容易创建(通过高级声明方法),因为它们是单个句子,避免了诉诸不必要且容易出错的临时程序。值得注意的是,FK约束的执行速度已由专门的程序员进行了高度优化(并且甚至几十年来,主要的平台供应商都在致力于此)。
此外,由于RDB必须是能够被多个应用程序(桌面,自动,Web,移动,其组合)访问的独立(自我保护,自我描述等)软件组件,因此不应与任何这些应用程序的代码“耦合”。
同样,作为重要的组织资源的数据自然倾向于不存在应用程序,应用程序程序员,应用程序开发平台和编程范例。
主键约束和重复行的含义
从概念上讲,当某种特定的事物在业务环境中被认为具有重要意义时,数据库建模人员必须(1)确定其相关特征(即其属性),并确认该事物作为实体实例原型,也就是说,实体类型-和(2)通过在逻辑设计中由一个或多个列集成的表来表示它。
然后,就像区分现实世界中给定实体类型的每个单独实例一样至关重要,表中包含的每一行也必须唯一地区分。如果一个表没有声明任何KEY,它将最终保留重复项,如果有两行或更多行保留完全相同的值,则它们都具有相同的含义,它们都表示相同的事实。
此时,由于多种原因,应丢弃重复的行。从理论上讲,设计者必须确保每一行总是唯一的,以使表在SQL数据子语言允许的范围内具有相关性(对数据操作有重要影响)。此外,从信息的角度来看,如果多行表示相同的事实,则记录它们不仅是多余的,而且是有害的,例如以下所示:
- 假设某人在某个表中插入了两个相同的行。
- 后来,其他人来了,只更新了一次重复项。结果,其他事件不再是最新的。
- 随后,另一个人更新了到目前为止尚未修改的事件。以这种方式,两个副本在不同的时间点经历了不同的变化。
- 之后,当某人对选择有关行所传达的信息感兴趣时,他或她可以找到该行的两个不同“版本”。
通过这种方式:
- 哪个“版本”可以被认为是正确,可靠的版本?
- 哪一个准确地反映了现实世界?
如您所知,这种现象甚至可能具有法律上的含义,这种情况无疑具有极其重要的意义。
此外,处理此类矛盾所花费的时间和精力(也许通过某种“更新同步”)应该更好地用于真正为组织创造价值的任务。因此,应通过设计避免保留矛盾的行,以保持数据库的完整性。
这就是为什么必须始终由数据库设计人员执行PRIMARY KEY(PK)的标识和相应约束的声明的原因。但也必须提及的是,一个表可能具有不止一个列或列的组合,其中包含唯一标识每一行的值。因此,除了设置PK约束(出于实用性原因理想地设置为PRIMARY)之外,设计人员还必须在适用时声明一个或多个ALTERNATE KEY(通常通过一个或多个UNIQUE加NOT NULL约束进行定义)很常见)。
PK的另一个有利特性是,当“迁移”到其他表以参与单个或复合FK时,它们可以帮助增强数据之间存在的关系的基数比。是的,所有这些都是通过DBMS确保的简单有效的声明设置来实现的。
(当前)CHECK约束和单行验证
让我们不要忘记(当前)CHECK约束的相关性,这些约束通过声明性地限制行的有效列值集(可能看起来很简单,但实际上是关系DBMS的基本特征),也有助于实现确保业务环境的规则始终准确地反映出来。
当您用MySQL标记标记问题时,必须指出的是,不幸的是,这样的平台允许声明这种约束,但是同时忽略了它的执行!可以理解的是,这种情况自2004年以来一直被报告为错误。
在这一点上,你将不得不通过其他方式,例如,为了照顾这个因素的ACID事务,触发器或数据库管理系统本身的其他方法(见本答案由@ypercubeᵀᴹ
有关此主题的信息),从而使数据继续始终如一。
声明约束:以声明方式建立更多的多行和多表业务规则
不论出于何种原因,包括MySQL在内的不同SQL DBMS都(即使有)支持程度很差的一个方面是以声明方式(显然是PK和FK之外)启用了多行和多表约束。
就其本身而言,SQL标准确实包含了很多年以来的ASSERTION。我不知道您的业务环境中的哪些规则将从该逻辑级别的验证方法中受益,但是作为数据库设计人员,我认为使用一个或多个ASSERTION约束数据非常方便,尽管我必须从从DBMS开发人员的角度来看,这种最重要的工具一直很难在物理抽象级别上实现。
自2016年以来,Oracle供应商和/或开发人员似乎正在评估 ASSERTION支持,这将使DBMS更加符合关系,从而更加健壮和更具竞争力。我猜想,如果(i)他们的使用者继续努力,并且(ii)Oracle成功实施,那么(iii)其他DBMS供应商/社区也必须启用它们,并且它们的使用范围将开始扩大。当然,这将是数据库管理领域的巨大进步,并且是Codd博士设想的最独特的工具之一,我个人希望我们很快会看到这种情况。
数据一致性和决策过程
如上所述,RDB的最重要方面之一是它自己保证所保留数据的一致性,并且只有当RDB遵守建模者声明的完整性约束时,才能满足所述一致性。
在这方面,必须具有受完整性保护的基表(在DDL结构中建立的基表),以便能够创建值得信赖的派生表(例如SELECT语句或从多个表中检索列的视图)。,因为必须根据基本表来生成派生表。
众所周知,人们将信息用作组织(和普通)决策过程中的主要工具。然后,如果数据库提供的信息不连贯且不准确,则基于此类信息的决策将不合理(至少可以说)。这就是为什么必须仔细设计和实施RDB的原因:应该将RDB构建为可靠的资源,可以帮助其用户做出有根据的决策。
“非正规化”
遗憾的是,“非规范化的数据库比规范化的数据库要快”,这是一个广泛传播的误解,尽管它也是可以从逻辑,物理和实用主义的角度加以反驳的论点。
首先,非规范化意味着必须预先对基表进行规范化(借助于在数据库的逻辑抽象级别上实现的基于科学的形式化程序)。
因此,假设该表实际上已正确归一化,则将其“去归一化”(与该词的形式含义相反,这涉及在表中附加属于广告中其他表的列,这些列也属于广告的其他表)临时方式)可能有助于(例如,在物理级别上)仅加快一个或几个特定SELECT语句的处理速度,而这种做法可能同时破坏许多其他关联数据的执行操作操作(例如,多个INSERT,UPDATE,DELETE和SELECT语句,或包含在单个或多个ACID事务中的它们的组合)。
此外,非规范化(正式或非正式)都会引入更新/修改异常,从而破坏数据库的一致性,而这可以通过复杂,昂贵且容易出错的过程来“解决”,而这一切都可以避免。一开始。
支持规范化和“非规范化”表的物理层架
打算在现实世界中使用的逻辑(抽象)布局(SQL-DDL设计)显然拥有必须考虑的物理(具体)影响。
以这种方式,“非规范化”表必定会“更宽”(容纳更多列),这意味着其行必定会更重(需要更多和更大的物理层组件),因此意味着底层计算过程(例如,那些与硬盘驱动器或内存有关的内容很容易变慢。
相反,归一化表格当然“更窄”(具有更少的列)将是“更轻”的元素(由越来越少的物理组件提供服务),其“表现得更快”,这将加快与例如数据写入和读取。
这样,非常方便(a)正式,谨慎地规范相关表,保持它们不变,然后(b)利用可以优化数据检索和修改速度的任何物理级别资源,例如,实现谨慎有效的索引策略,启用正确的软件和硬件服务器配置,升级网络带宽功能等。
正在考虑的数据库的功能
问题的以下几段与数据检索操作的速度有关:
[A]如果产品“有效”,则在增强数据库方面犹豫不决;不过,我注意到的第一件事是一页加载需要1分钟(是的,需要60秒!)。
如果某个页面的负载如此之大,则很明显,系统的用户无法获得良好的服务;因此,即使“工作”起来,它的功能似乎也不是最优的,这表明您有意维持整个环境(数据库和应用程序)效率更高的意图,并且表现出非常建设性的态度。
然后,即使科学绝对支持您,因此您也应保持坚定的态度,但我还是建议您以外交方式处理此情况,因为最终,您的雇主,同事和您自己正在共同努力,以使整个组织更成功。因此,这是您应该强调的一个论据,即尽管他们在做其他事情时做得很好,但是改善常规和特定数据管理实践可以极大地帮助实现组织和个人的增长。
大多数相关查询都包含JOIN操作,这使它们在处理大量数据(数据库包含数百万行)时非常非常非常慢地运行。
值得注意的是,JOIN运算符是与数据的关系处理有关的必不可少且功能强大的元素。然后,尽管功能更强大的平台以相对更快的执行速度为其提供了服务,但是您描述的情况很可能是效率低下的设计(在抽象的概念,逻辑和物理级别)的症状。因此,我的第一眼估计是:
- INDEX设置可能需要改进。
- PK和FK列的类型和大小定义需要进行审查(并且我完全同意@Rick James的PK 注意事项,因为在适当的情况下,复合KEY往往比附加的代理更有效)。
- 由于在适当的情况下(即在设计良好的RDB中执行),JOIN执行得非常快,因此进一步的(基于科学的正式)规范化可能有助于减轻这些问题。
此外,是的,正如@TommCatt在他的回答中提到的那样,有时对查询的(逻辑)重写会修改其(物理)执行计划,从而加速数据的读取/写入,这是一个应明确考虑的因素。