我一直认为数据库应该针对读取性能进行非规范化,因为它是为OLAP数据库设计完成的,而不是为OLTP设计进一步夸大3NF。
例如,在Performance of different aproaches to time-based data的各种帖子中,PerformanceDBA捍卫了数据库应该始终通过归一化到5NF和6NF(正常形式)来精心设计的范例。
我是否理解正确(以及我理解的是什么)?
OLAP数据库(低于3NF)的传统非规范化方法/范例设计有什么问题,以及3NF足以满足大多数OLTP数据库实际情况的建议?
例如:
我应该承认,我永远无法理解非规范化有助于读取性能的理论。任何人都可以给我参考,对这个和相反的信念有很好的逻辑解释吗?
在试图说服我的利益相关者说OLAP / Data Warehousing数据库应该规范化时,我可以参考哪些来源?
为了提高可见度,我从评论中复制了这里
“如果参与者在他们看到或参与过的6NF中添加(披露)有多少现实生活(没有包含科学项目)的数据仓库实施,那将是一件好事。快速集合.Me = 0。” - Damir Sudarevic
Wikipedia's Data Warehouse article告诉:
“标准化的方法[与Ralph Kimball的维度相比],也称为3NF模型(第三范式),其支持者被称为”Inmonites“,相信Bill Inmon的方法,其中声明数据仓库应该是使用ER模型/标准化模型建模。“
看起来规范化的数据仓库方法(Bill Inmon)被认为不超过3NF(?)
我只是想了解数据仓库/ OLAP是非规范化的同义词的神话(或无处不在的公理信念)的起源是什么?
达米尔苏达雷维奇回答说他们铺好了道路。让我回到这个问题:为什么反规范化被认为有助于阅读?
神话
我一直认为数据库应该被非规范化用于读取,因为它是为OLAP数据库设计完成的,而不是为OLTP设计进一步夸大3NF。
这种效果有一个神话。在关系数据库上下文中,我重新实现了六个非常大的所谓“非规范化”“数据库”;并执行超过八十项任务,纠正其他人的问题,只需将其标准化,应用标准和工程原则。我从未见过任何有关神话的证据。只有人们重复咒语,好像它是某种神奇的祈祷。
标准化与非标准化
(“反规范化”是一个欺诈性的术语,我拒绝使用它。)
这是一个科学行业(至少可以提供不会破坏的软件;让人们登上月球;运行银行系统等等)。它受物理定律的支配,而不是魔法。计算机和软件都是有限的,有形的物理对象,受物理定律的约束。根据我收到的中等和高等教育:
因此,总体结果是更高,更高的性能。
根据我的经验,即从同一个数据库提供OLTP和OLAP,从来没有必要对我的规范化结构进行“反规范化”,以获得更高的只读(OLAP)查询速度。这也是一个神话。
很多书都是由人写的,卖的是神话。需要认识到这些是非技术人员;因为他们销售魔术,他们销售的魔力没有科学依据,他们在销售宣传中方便地避开了物理定律。
(对于任何想要对上述物理科学提出异议的人,只重复咒语不会产生任何影响,请提供支持口头禅的具体证据。)
为什么神话会流行?
嗯,首先,它在科学类型中并不普遍,它们没有寻求克服物理定律的方法。
根据我的经验,我发现了流行的三个主要原因:
我的答案
如果我回答你问题的每一部分,或者如果我回答其他一些答案中的错误元素,那么这个答案将会非常漫长。例如。以上只回答了一个项目。因此,我将在不解决具体组件的情况下回答您的问题,并采取不同的方法。我只会处理与你的问题有关的科学,我是合格的,并且非常有经验。
让我以可管理的部分向您展示科学。 六个大规模完整实施任务的典型模型。
所以我们考虑了物理定律,我们应用了一点科学。 我们实施了标准概念,即数据属于公司(而不是部门),公司需要一个版本的事实。数据库是纯粹的关系,规范化为5NF。纯开放式架构,以便任何应用程序或报表工具都可以访问它。存储过程中的所有事务(与整个网络中不受控制的SQL字符串相对)。在我们的“高级”教育之后,每个应用程序的相同开发人员编写了新应用程序。
科学显然是有效的。嗯,这不是我的私人科学或魔术,而是普通工程和物理定律。所有这些都在一个数据库服务器平台上运行;两对(生产和DR)的服务器退役并交给另一个部门。总共720GB的5个“数据库”被归一化为一个总计450GB的数据库。将大约700个表(许多重复列和重复列)标准化为500个未重复的表。它表现得更快,总体速度提高了10倍,而且在某些功能上提速超过100倍。这并没有让我感到惊讶,因为那是我的意图,科学预测了它,但它让人们惊叹于咒语。
更多规范化
好吧,在每个项目中都取得了标准化的成功,并且对所涉及的科学充满了信心,对于标准化更多而不是更少,这是一个自然的进展。在过去,3NF已经足够好了,后来的NF还没有确定。在过去的20年里,我只提供了零更新异常的数据库,所以事实证明,今天的NF定义,我总是提供5NF。
同样,5NF很棒,但它有其局限性。例如。透过大表(根据MS PIVOT扩展而不是小结果集)很慢。所以我(和其他人)开发了一种提供规范化表格的方法,使得透视是(a)简单和(b)非常快。事实证明,现在已经定义了6NF,那些表是6NF。
由于我从同一个数据库提供OLAP和OLTP,我发现,与科学一致,结构的标准化程度越高:
所以,是的,我有一致和不变的经验,不仅标准化得多,比非标准化或“非标准化”快得多;更多标准化甚至比标准化程度更低。
成功的一个标志是功能的增长(失败的迹象是尺寸的增长而不增加功能)。这意味着他们立即要求我们提供更多报告功能,这意味着我们更加规范化,并提供更多这些专业表(多年后证明是6NF)。
在这个主题上取得进展。我一直是数据库专家,而不是数据仓库专家,所以我的前几个项目仓库并不是完整的实现,而是他们实质性的性能调整任务。对于我专注的产品,他们在我的范围内。 让我们不要担心标准化的确切程度等,因为我们正在研究典型案例。我们可以认为OLTP数据库已经合理规范化,但不能支持OLAP,组织购买了一个完全独立的OLAP平台,硬件;投资开发和维护大量ETL代码;然后,在实施之后,他们花了一半的时间来管理他们创建的重复项。在这里,书籍编写者和供应商需要受到指责,因为大量浪费的硬件和单独的平台软件许可证导致组织购买。
同时,回到农场(上面的5NF数据库),我们不断添加越来越多的OLAP功能。确实应用程序功能增长了,但这很少,业务没有改变。他们会要求更多6NF并且很容易提供(5NF到6NF是一小步; 0NF对任何东西,更不用说5NF,是一个很大的一步;有组织的架构很容易扩展)。
OLTP和OLAP(单独的OLAP平台软件的基本理由)之间的一个主要区别是OLTP是面向行的,它需要事务安全的行,而且速度快;并且OLAP不关心事务性问题,它需要列和快速。这就是所有高端BI或OLAP平台都是面向列的原因,这就是为什么OLAP模型(Star Schema,Dimension-Fact)是面向列的原因。
但是使用6NF表:
根据定义,我们多年来一直提供的是关系数据库,OLTP使用至少为5NF,OLAP要求为6NF。
我们唯一没有做的就是从一个新项目开始,并从一开始就申报纯粹的6NF。这就是我接下来要排队的。
什么是第六范式?
假设你有一个规范化的句柄(我不打算在这里定义),与这个线程相关的非学术定义如下。请注意,它适用于表级别,因此您可以在同一数据库中混合使用5NF和6NF表:
6NF看起来像什么?
数据模型属于客户,我们的知识产权不适用于免费出版。但我确实参加了这个网站,并提供了问题的具体答案。您确实需要一个真实的示例,因此我将为其中一个内部实用程序发布数据模型。
这是为任何时期的任何客户收集服务器监控数据(企业级数据库服务器和操作系统)。我们使用它来远程分析性能问题,并验证我们所做的任何性能调优。该结构在十多年内没有变化(增加,现有结构没有变化),多年后被确定为6NF的专业5NF的典型特征。允许完全旋转;在任何尺寸上绘制的任何图表或图形(提供22个枢轴,但这不是限制);切片和骰子;连连看。请注意,它们都是尺寸。
监控数据或度量标准或向量可以改变(服务器版本更改;我们想要更多的东西)而不影响模型(你可能记得在另一篇文章中我说过EAV是6NF的私生子;这是完整的6NF,未经稀释的父亲,因此提供EAV的所有功能,而不牺牲任何标准,完整性或关系权力);你只需要添加行。
▶Monitor Statistics Data Model◀。 (对于内联来说太大;有些浏览器无法加载内联;请单击链接)
它允许我在收到客户的原始监控统计文件后生成这些▶Charts Like This◀,六次击键。注意混合搭配;操作系统和服务器在同一图表上;各种各样的Pivots。 (经许可使用。)
不熟悉关系数据库建模标准的读者可能会发现▶IDEF1X Notation◀很有帮助。
6NF数据仓库
这最近由Anchor Modeling验证,因为他们现在将6NF作为数据仓库的“下一代”OLAP模型。 (它们不提供单一版本数据的OLTP和OLAP,这是我们自己的)。
数据仓库(仅)经验
我对数据仓库的经验(不是上述6NF OLTP-OLAP数据库)已经完成了几项主要任务,而不是完整的实施项目。结果并不令人意外:
有科学头脑的人不这样做;他们不相信或依赖银子弹和魔法;他们使用和努力工作科学来解决他们的问题。
有效的数据仓库理由
这就是为什么我在其他帖子中说过,单独的数据仓库平台,硬件,ETL,维护等的唯一有效理由是有许多数据库或“数据库”,所有数据库或“数据库”都被合并到一个中央仓库,用于报告和OLAP。
金博尔
关于Kimball的一个词是必要的,因为他是数据仓库中“对性能进行非规范化”的主要支持者。根据我上面的定义,他是那些在他们的生活中显然从未正常化的人之一;他的出发点是非标准化的(被伪装成“去标准化”),他只是在Dimension-Fact模型中实现了它。
所有的故事,一个神话中的一部分,它们在一起并相互支持。
你的使命
你应该选择接受吗?我要求你为自己思考,并停止娱乐任何与科学和物理定律相矛盾的想法。无论它们有多么普遍或神秘或神话。在信任之前寻求任何证据。要科学,为自己验证新的信念。重复“为性能而去标准化”的口号不会使您的数据库更快,它只会让您感觉更好。就像坐在场边的肥胖小孩告诉自己,他比竞争中的所有小孩跑得更快。
问题?
非规范化和聚合是用于在数据仓库中实现性能的两种主要策略。建议它不会提高读取性能是愚蠢的!当然,我一定在这里误解了一些东西?
聚合:考虑一个持有10亿购买的表。将其与持有一行的表格进行对比。现在哪个更快?从十亿行表中选择总和(金额)还是从一行表中选择金额?这当然是一个愚蠢的例子,但它很清楚地说明了聚合的原理。为什么它更快?因为无论我们使用什么神奇的模型/硬件/软件/宗教,读取100字节比读取100千兆字节更快。就那么简单。
非规范化:零售数据仓库中的典型产品维度具有大量列。有些列很简单,比如“Name”或“Color”,但它也有一些复杂的东西,比如层次结构。多个层次结构(产品范围(5个级别),预期买方(3个级别),原材料(8个级别),生产方式(8个级别)以及几个计算数字,例如平均提前期(自年初以来) ,重量/包装措施etcetera etcetera。我维护了一个200多列的产品维度表,它是由来自5个不同源系统的约70个表构建的。讨论是否对规范化模型进行查询(下图)是很愚蠢的
select product_id
from table1
join table2 on(keys)
join (select average(..)
from one_billion_row_table
where lastyear = ...) on(keys)
join ...table70
where function_with_fuzzy_matching(table1.cola, table37.colb) > 0.7
and exists(select ... from )
and not exists(select ...)
and table20.version_id = (select max(v_id from product_ver where ...)
and average_price between 10 and 20
and product_range = 'High-Profile'
...比非规范化模型上的等效查询更快:
select product_id
from product_denormalized
where average_price between 10 and 20
and product_range = 'High-Profile';
为什么?部分出于与聚合场景相同的原因。但也因为查询只是“复杂”。它们非常令人厌恶,以至于优化器(现在我正在使用Oracle的细节)变得困惑并搞砸了执行计划。如果查询处理少量数据,则次优执行计划可能不是那么重要。但是一旦我们开始加入大表,数据库就能正确地获得执行计划是至关重要的。使用单个同步密钥对一个表中的数据进行非规范化(哎呀,为什么我不为这个正在进行的火灾添加更多燃料),过滤器成为预先制作的列上的简单范围/相等过滤器。将数据复制到新列使我们能够收集有关列的统计信息,这将有助于优化器估计选择性,从而为我们提供正确的执行计划(好吧......)。
显然,使用非规范化和聚合使得更难以适应模式更改这是一件坏事。另一方面,它们提供了读取性能,这是一件好事。
那么,您是否应该对数据库进行非规范化以实现读取性能?一定不行!它为您的系统增加了许多复杂性,以至于在您交付之前,它将以多少方式阻止您。这值得么?是的,有时您需要这样做才能满足特定的性能要求。
更新1
PerformanceDBA: 1 row would get updated a billion times a day
这意味着(接近)实时要求(反过来会产生一组完全不同的技术要求)。许多(如果不是大多数)数据仓库没有这个要求。我选择了一个不切实际的聚合示例,只是为了明确聚合的工作原理。我不想也要解释汇总策略:)
此外,还必须对比数据仓库的典型用户和底层OLTP系统的典型用户的需求。如果有50%的当前数据丢失,或者10辆卡车爆炸并导致司机死亡,那么用户希望了解哪些因素会降低运输成本。进行2年以上数据分析仍然可以得出相同的结论,即使他必须掌握第二时间的最新信息。
将其与卡车司机(幸存者)的需求进行对比。他们不能在某个转接点等待5个小时,因为一些愚蠢的聚合过程必须芬兰语。拥有两个单独的数据副本可以解决这两个需求。
与操作系统和报告系统共享同一组数据的另一个主要障碍是,发布周期,问答,部署,SLA以及您拥有的是非常不同的。同样,有两个单独的副本使这更容易处理。
通过“OLAP”我理解你是指用于决策支持的面向主题的关系/ SQL数据库 - AKA是一个数据仓库。
Normal Form(通常为5th / 6th Normal Form)通常是数据仓库的最佳模型。规范化数据仓库的原因与任何其他数据库完全相同:它减少了冗余并避免了潜在的更新异常;它避免了内置偏差,因此是支持模式更改和新要求的最简单方法。在数据仓库中使用Normal Form还有助于保持数据加载过程的简单和一致。
没有“传统的”非规范化方法。良好的数据仓库一直都是规范化的。
数据库是否应该针对读取性能进行非规范化?
好的,这里总共“你的里程可能会变化”,“它取决于”,“为每个工作使用适当的工具”,“一个尺寸不适合所有”的答案,有点“不要修复它如果它不是破碎的“投入:
非规范化是在某些情况下提高查询性能的一种方法。在其他情况下,它实际上可能会降低性能(因为磁盘使用量增加)。它肯定会使更新变得更加困难。
只有当您遇到性能问题时才应该考虑它(因为您正在提供规范化的好处并引入复杂性)。
非规范化的缺点不是从未更新的数据或仅在批处理作业中更新的数据的问题,即不是OLTP数据。
如果非规范化解决了您需要解决的性能问题,并且侵入性较小的技术(如索引或缓存或购买更大的服务器)无法解决,那么是的,您应该这样做。
先是我的意见,然后是一些分析
意见 非规范化被认为有助于读取数据,因为非正规化这个词的共同使用通常不仅包括破坏正常形式,还包括将任何插入,更新和删除依赖性引入系统。
严格来说,这是错误的,请参阅此question/answer,严格意义上的非规范化意味着打破1NF-6NF的任何正常形式,其他插入,更新和删除依赖关系用Principle of Orthogonal Design解决。
所以会发生的是人们拿Space vs Time tradeoff principle并记住术语冗余(与非正规化相关,仍然不等于它)并得出结论,你应该有好处。这是错误的含义,但错误的含义不允许您得出相反的结论。
打破正常形式可能确实加速了一些数据检索(下面的分析中的细节),但通常它也会同时:
分析
因此,我声称有时打破正常形式可以帮助检索。是时候提出一些论点了
1)打破1NF
假设您有6NF的财务记录。从这样的数据库中,您肯定可以获得每个帐户每月余额的报告。
假设一个必须计算此类报告的查询需要通过n条记录,您可以创建一个表
account_balances(month, report)
这将保存每个帐户的XML结构余额。这会打破1NF(请参阅后面的说明),但允许使用最小I / O执行一个特定查询。
同时,假设可以通过插入,更新或删除财务记录来更新任何月份,系统上的更新查询的性能可能会因与每次更新的某个n函数成比例的时间而减慢。 (上面的例子说明了一个原则,实际上你会有更好的选择,并且获得最小I / O的好处会带来这样的惩罚:对于实际更新数据的实际系统,即使对于你的目标查询,你也会得到不好的性能,具体取决于实际工作量的类型;如果需要,可以更详细地解释这一点)
注意:这实际上是一个简单的例子,它有一个问题 - 1NF的定义。假设上述模型打破1NF是根据要求,属性的值'恰好包含来自适用域的一个值'。
这允许你说属性报告的域是一组所有可能的报告,并且从所有这些报告中只有一个值并声称1NF没有被破坏(类似于存储单词不会破坏1NF的参数,即使你可能在你的模型中某处有letters
关系)。
另一方面,有更好的方法可以对此表进行建模,这对于更广泛的查询更有用(例如,为一年中的所有月份检索单个帐户的余额)。在这种情况下,你可以通过说这个字段不在1NF中来证明这种改进。
无论如何,它解释了为什么人们声称打破NF可能会提高性能。
2)打破3NF
假设3NF中的表格
CREATE TABLE `t` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`member_id` int(10) unsigned NOT NULL,
`status` tinyint(3) unsigned NOT NULL,
`amount` decimal(10,2) NOT NULL,
`opening` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `member_id` (`member_id`),
CONSTRAINT `t_ibfk_1` FOREIGN KEY (`member_id`) REFERENCES `m` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB
CREATE TABLE `m` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
带有样本数据(t为1M行,m为100k)
假设您要改进的常见查询
mysql> select sql_no_cache m.name, count(*)
from t join m on t.member_id = m.id
where t.id between 100000 and 500000 group by m.name;
+-------+----------+
| name | count(*) |
+-------+----------+
| omega | 11 |
| test | 8 |
| test3 | 399982 |
+-------+----------+
3 rows in set (1.08 sec)
你可以找到将属性name
移动到打破3NF的表m的建议(它有一个FD:member_id - > name和member_id不是t的关键字)
后
alter table t add column varchar(255);
update t inner join m on t.member_id = t.id set t.name = m.name;
赛跑
mysql> select sql_no_cache name, count(*)
from t where id
between 100000 and 500000
group by name;
+-------+----------+
| name | count(*) |
+-------+----------+
| omega | 11 |
| test | 8 |
| test3 | 399982 |
+-------+----------+
3 rows in set (0.41 sec)
注意:上面的查询执行时间减少了一半,但是
从长远来看,规范化是正确的方法。但是你并不总是可以选择重新设计公司的ERP(例如,已经只有3NF) - 有时你必须在给定的资源范围内完成某项任务。当然这样做只是短期的“解决方案”。
底线
我认为对你的问题最恰当的答案是,你会发现行业和教育使用“非正规化”一词
因此,在严格定义下,聚合(汇总表)不被视为非规范化,它们在性能方面可以提供很多帮助(任何缓存都不会被视为非规范化)。
松散的用法包括破坏正常形式和principle of orthogonal design,如前所述。
可能会产生一些亮点的另一件事是逻辑模型和物理模型之间存在非常重要的差异。
例如索引存储冗余数据,但没有人认为它们是非规范化的,甚至没有人使用松散的术语,并且有两个(连接)原因
如果您无法正确建模您的逻辑模型,您将最终得到不一致的数据库 - 您的实体之间的关系类型错误(无法表示问题空间),冲突的事实(松散信息的能力),您应该采用任何方法来获取一个正确的逻辑模型,它是将在其上构建的所有应用程序的基础。
谓词的规范化,正交和清晰语义,定义良好的属性,正确识别的函数依赖性都是避免陷阱的一个因素。
在物理实现方面,事情变得更加放松,因为依赖于非密钥的物理化计算列可能会破坏3NF,但如果有机制保证一致性,则物理模型中允许的方式与索引相同是允许的,但你必须非常仔细地证明它是正确的,因为通常标准化将产生相同或更好的全面改进,并且没有或更少的负面影响,并将保持设计清晰(这降低了应用程序开发和维护成本),从而节省您可以轻松地花在升级硬件上以提高速度,甚至超过破坏NF所能达到的速度。
构建数据仓库(DW)的两种最流行的方法似乎是Bill Inmon和Ralph Kimball。
Inmon的方法使用标准化方法,而Kimball使用维度建模 - 去标准化的星型模式。
两者都有很好的文档记录到小细节,并且都有许多成功的实现。两者都为DW目的地提供了“宽阔,铺设良好的道路”。
我不能评论6NF方法和Anchor Modeling,因为我从未见过或参与过使用该方法的DW项目。在实现方面,我喜欢沿着经过良好测试的路径旅行 - 但是,这只是我。
那么,总结一下,DW应该归一化还是去规范化?取决于您选择的方法 - 只需选择一个并坚持下去,至少直到项目结束。
编辑 - 一个例子
在我目前工作的地方,我们有一个遗留报告,它一直在生产服务器上运行。这不是一份简单的报告,而是每天通过电子邮件发送给每个人和他的蚂蚁的30份子报告。
最近,我们实施了DW。有两个报表服务器和一堆报告,我希望我们可以忘记遗留的事情。但不是,遗产是遗产,我们总是拥有它,所以我们想要它,需要它,不能没有它,等等。
问题是python脚本和SQL的混乱需要花费8个小时(是的,e-i-g-h-t小时)来运行每一天。毋庸置疑,数据库和应用程序是由少数开发人员多年建立的 - 所以,不完全是你的5NF。
是时候从DW重新创建遗留物了。好吧,为了做到这一点,它已经完成了,需要3分钟(t-h-r-e-e分钟)来制作它,每个子报告需要6秒钟。而且我急于交付,所以甚至没有优化所有查询。这是8 * 60/3 = 160倍的因素 - 更不用说从生产服务器中删除8小时作业的好处了。我想我仍然可以刮一分钟左右,但现在没有人关心。
作为一个兴趣点,我使用了Kimball的DW方法(维度建模),这个故事中使用的所有内容都是开源的。
我认为这就是所有这些(数据仓库)应该是什么。是否使用了哪种方法(标准化或非标准化)?
编辑2
作为一个兴趣点,Bill Inmon在他的网站上有一篇写得很好的论文 - A Tale of Two Architectures。
“非正规化”这个词的问题在于它没有指明要进入的方向。它就像试图从纽约开车离开芝加哥去旧金山。
星型模式或雪花模式肯定没有规范化。在某些使用模式中,它肯定比标准化模式表现更好。但是有些非规范化的情况下,设计师根本没有遵循任何规则,只是凭直觉组成表格。有时这些努力并没有成功。
简而言之,不要只是反规范化。如果您对其好处充满信心,即使它不符合标准化设计,也要遵循不同的设计规则。但是不要使用非规范化作为随意设计的借口。
简短的回答是不解决你没有的性能问题!
对于基于时间的表,通常接受的pardigm是在每一行中具有valid_from和valid_to日期。这基本上仍然是3NF,因为它只是将语义从“这是这个实体的唯一一个版本”改为“这是此实体的唯一版本”
简化:
应该对OLTP数据库进行规范化(只要有意义)。
应将OLAP数据仓库非规范化为Fact和Dimension表(以最小化连接)。