数据库设计方式不同大部分时间我们可以使用学校实例:数据库规范化和所有事物都正常工作但有些情况需要另一种方法可删除引用以获取更多灵活性万事按书办时 得提高性能呢在这种情况下,非正态化是一种技术,我们应该加以考虑文章中,我们将讨论非正态化的利弊, 以及哪些情境需要它
异常化是什么
异常化策略使用于先前规范化数据库提高性能背后的想法是添加冗余数据 我们认为它最能帮助我们现有表格中可使用额外属性、添加新表或甚至创建现有表实例常用目标是减少选择查询的运行时间,使查询更容易获取数据或单表生成汇总报告这一过程可带来新问题,待会再讨论
归并数据库是反正规化过程的起始点与数据库相区别很重要 数据库未实现正常化 数据库先实现正常化 后实现反正常化第二位算法优先往往是数据库设计不良或知识缺失的结果
示例:简单CRM范式
下模型将作为我们的例子
快速查看表
- 上头
用户记账
表格存储用户登录程序数据(简化模型、角色和用户权限不在此列)。 - 上头
客户端
表格中包含一些客户基础数据 - 上头
产品化
表单向客户提供产品 - 上头
任务设置
表格包含所有任务可视每项任务为对客户的一组相关动作每项任务都有相关电话、会议以及出价和售价产品列表 - 上头
调用
并会话
表格存储所有通话和会议数据并连接任务用户 - 词典
任务输出
,会议结果
并点名出局
包含任务、会议或调用最终状态所有可能的选项 - 上头
fact_offer
存储向客户提供某些任务时所有产品列表产品发售
内含客户实际购买的所有产品列表 - 上头
support_order
表存储数据 所有订单我们已经设置products_on_order
表单产品和数量供特定订单使用 - 上头
注销
表列因事故或类似原因注销的产品列表破镜)
数据库简化化,但完全规范化找不到冗余,它应该做作业在任何情况下,我们都不应该经历性能问题, 只要我们用相对小量的数据工作
时间和理由使用异常化
和几乎任何东西一样,你必须确定你为什么想应用非正态化需要确定使用所得大于任何伤害有一些情境你绝对应该想到非正态化
- 维护历史 :数据可随时间变化,我们需要存储记录创建时有效值什么样的变化我们指人名变换客户也可以更改业务名或任何其他数据任务细节应包含生成任务时实际值万一不发生,我们无法正确重创过去数据通过添加含有这些修改历史的表,我们可以解决这个问题在这种情况下,选择查询返回任务和有效客户名会变得更加复杂可能多一张表不是最佳解决之道
- 提高查询性能部分查询可能使用多表访问我们经常需要的数据想想一种状况 我们需要加入十表 返回客户名 和产品出售沿路的一些表还可能包含大量数据那样的话 增加一个比较明智
客户端_id
直接属性产品发售
表格内 - 加速报告:频繁需要某些统计从直播数据创建系统耗时颇多,并可能影响系统整体性能假设我们想追踪客户销售 某些年对部分客户或所有客户生成实数据报告几乎会在整个数据库中进行“排查”,并经常减慢速度万一常使用统计呢
- 计算前端常用值想要一些即时计算值 免得实时生成
必须指出这一点无性能问题时无需反正化内程序但如果你注意到系统减速-或你意识到可能发生-你应该考虑应用这一技术使用前先考虑其他选项,例如查询优化和适当索引化正常化后也可以使用,但最好解决开发阶段的问题
异常化的缺陷是什么
很明显,非正常化进程的最大优势是提高性能代价可以包括:
- 磁盘空间 :期望这一点,因为我们有重复数据
- 数据异常我们必须非常清楚事实,即现在数据可以多处修改我们必须相应调整每件重复数据计算值报表也是如此通过触发程序、交易和/或程序实现这一点,所有操作必须一起完成
- 文献资料:我们必须正确记录我们应用的所有非正常化规则等下修改数据库设计时 需要查看所有异常 并重考可能我们用不着了 因为我们解决了问题或也许我们需要加进现有的非正常化规则举例:我们为客户表添加新属性并存储历史值和所有我们已经存储的东西改变现有非正常化规则实现这一点
- 减慢其他运算 :可期望慢化数据插入、修改和删除操作如果这些操作相对少见,则可能大有裨益基本说来,我们将慢选一分进更多慢插/更新/删除查询复杂选择技术可明显减慢整个系统,但减慢多小操作不应损害应用的可用性
- 多编码 :规则2和3需要附加编码,但同时将大量简化部分选择查询if we're反正规化现有数据库 we'll have to 修改这些选择查询 以获取我们工作的好处并更新新加属性还需要多编码
示例模型失序
在下文模型中,我应用了一些前文提到的非正常化规则粉色表已经修改,光蓝表则完全新
应用什么变化和原因
唯一变化产品化
表格加法unit_in_stock
属性在一个归并模型中,我们可以计算数据为单元订购-单元出售-单元注销.客户每次请求产品时,我们都会重复计算,这将耗时极多。取而代之的是前方计算值客户请求时,我们会备妥精选查询大都简化反之,unit_in_stock
属性必须在插入、更新或删除后调整products_on_order
,注销
,fact_offer
并产品发售
表格中
中修改任务设置
表格中发现两个新属性:客户端名
并user_first_last_name
.两者都存储任务创建时的值原因是这两个值都可随时间变化并保留外国密钥 连接原客户名和用户名多值存储像客户地址 VATID
异常化fact_offer
表有2个新属性物价单
并价钱
.上头物价单
属性存储是因为我们需要存储实值时产品提供.归并模型只显示当前状态,所以当产品价格改变我们的历史价格时,也会改变。我们的改变并不仅仅使数据库运行速度更快:它也使数据库工作效果更好上头价钱
属性计算值单位发售
*物价单
.避免每次我们想查看提供产品列表时计算出成本微小,但能提高性能
上修改产品发售
表格非常相似 。表格结构不变,但存储了售品列表
上头statistics_per_year
表格完全新到模型我们应当视之为非规范化表,因为所有数据都可以从其他表计算支持此表的想法是存储任务数、成功任务数、会议数和电话数中心还处理每年总收费后插入、更新或删除任务设置
,会话
,调用
并产品发售
表格,我们应该重新计算表数据 客户端和对应年份可期望我们大都改变 本年度前些年报告不必修改
值表前排计算, 等时需要计算结果时, 我们花少时间和资源想想你经常需要的值可能你不会定期需要全部 并冒着计算部分直播的风险
异常化是一个非常有趣和强势概念虽然这不是你应该想到的提高性能的首创, 在某些情况下它可能是最佳或甚至唯一解决办法
选择解析前,请确定自己想要做点分析并跟踪性能上线后你可能决定去变形不要害怕使用它,但跟踪变化,你不应该经历任何问题(即可怕的数据异常)。