我的雇主是一家小型办公用品公司,正在更换供应商,我正在浏览他们的电子内容,以得出一个强大的数据库模式;我们之前的模式几乎是在没有任何思考的情况下拼凑在一起的,这几乎导致了一个令人难以忍受的数据模型,其中包含损坏的、不一致的信息。

新供应商的数据比旧供应商的好很多,但他们的数据就是我所说的 超正常化. 。例如,他们的产品类别结构有5个级别:主部门、部门、类、子类、产品块。此外,产品块内容具有产品的长描述、搜索词和图像名称(其想法是产品块包含产品和所有变体 - 例如一支特定的钢笔可能有黑色、蓝色或红色墨水;所有这些项目本质上都是同一件事,因此它们适用于单个产品块)。在我提供的数据中,这表示为产品表(我说“表”,但它是一个包含数据的平面文件),其中包含对产品块的唯一 ID 的引用。

我正在尝试提出一个强大的模式来容纳我提供的数据,因为我需要相对较快地加载它,并且他们给我的数据似乎与他们提供的数据类型不匹配在他们的示例网站上提供演示(http://www.iteminfo.com)。无论如何,我不打算重用他们的演示结构,因此这是一个有争议的问题,但我正在浏览该网站以获取有关如何构建事物的一些想法。

我不确定的是我是否应该以这种格式保存数据,或者例如使用自引用关系将主/部门/类/子类合并到单个“类别”表中,并将其链接到产品块(产品块应保持独立,因为它本身不是“类别”,而是给定类别的一组相关产品)。目前,产品块表引用子类表,因此如果我将它们合并在一起,这将更改为“category_id”。

我可能会使用 Ruby on Rails 来创建一个电子商务店面(或者这是我的计划),所以我试图避免以后遇到麻烦或应用程序臃肿 - 也许我我想得太多了,但我宁愿安全也不愿后悔;我们之前的数据确实一团糟,由于数据不一致和不准确,给公司造成了数万美元的销售损失。另外,我将稍微打破 Rails 约定,确保我的数据库稳健并强制执行约束(我也计划在应用程序级别执行此操作),所以这也是我需要考虑的事情。

遇到这样的情况你会如何处理?请记住,我已经将数据加载到模拟表结构的平面文件中(我有文档说明哪些列是哪些列以及设置了哪些引用);我正在尝试决定是否应该让它们像现在一样正常化,或者我是否应该寻求整合;我需要了解每种方法将如何影响我使用 Rails 对站点进行编程的方式,因为如果我进行合并,单个表中基本上会有 4 个“级别”的类别,但这肯定比单独的表更易于管理每个级别,因为除了子类(直接链接到产品块)之外,它们不 除了显示其下一级类别之外的任何内容。我总是对处理这样的数据的“最佳”方式感到困惑——我知道这样一句话:“规范化直到它受伤,然后非规范化直到它起作用”,但直到现在我才真正需要实现它。

有帮助吗?

解决方案

我宁愿在反规范数据模型中的“hypernormalized”的方法。你所提到的自参考表可能减少表的数量下降,在某些方面简化生活,但一般这种类型的关系可能会非常棘手,处理。分层查询成为一种痛苦一样,映射对象模型这个(如果你决定走这条路)。

一对额外的联接不会伤害,并会保持应用程序更易于维护。除非性能降低,由于加入的数量过多,我会选择离开的东西像他们。作为额外的奖励,如果这些水平表所需的附加功能添加的,你不会因为你合并他们全部进入自引用表碰到的问题。

其他提示

我完全有关父子层次结构自引用表结构的批评不以为然。链表结构使得UI和业务层的编程更简单,更易于维护在大多数情况下,因为链表和树来表示的UI和业务层通常在执行语言中,这数据自然的方式。

关于这些结构保持数据完整性约束的难度的批评是完全有效的,尽管简单的解决方案是使用承载更难检查约束的封闭表。闭合表容易地保持与触发器。

代价是在DB(闭包表和触发器)为少了很多在UI和业务层代码复杂一些额外的复杂性。

如果我理解正确的话,你想利用自己单独的表,然后将它们清楚交代保存在一个表层次结构的自引用FK。

这通常是一种更灵活的方式(例如,如果你想添加一个第五级),但SQL和关系数据模型不倾向于像这样的链表很好地工作,即使像MS SQL新语法服务器的CTE。无可否认,热膨胀系数使得尽管它好多了。

有可能是困难和昂贵的执行的东西,像这样的产品必须始终是对层次等的第四级。

如果你决定做这种方式的话,肯定检查了乔·塞科的 SQL对于聪明豆,我相信有一个或两个部分建模和SQL与层次结构的工作或更好,但让他一个致力于向主体(的乔Celko的树木和层次结构)。

Normalization意味着数据的完整性,即:每一个正常形式,降低,你的数据不一致的情况下,数

作为一项规则,denormalization具有更快的querying的目标,但是导致增加的空间,增加DML时间,以及最后但并非最不重要,加大力度,使数据保持一致。

一通常更快写入代码(写入速度更快,而不是代码更快)和代码是不易出错,如果数据是normalized

自引用表几乎总是变成是更糟糕查询和比归一化的表执行差。不这样做。它看起来可能对你更优雅,但它不是,是一个非常贫穷的数据库设计技术。个人您所描述的结构听起来蛮好我不hypernormalized。一个正确规范化的数据库(如需要可进行复杂的规则外键约束以及缺省值,触发器()和数据验证约束),也远远更有可能具有一致和准确的数据。我同意让数据库执行规则,可能这就是为什么过去的应用程序有坏的数据,因为规则没有在适当的地方执行,人们能够很容易地周围得到的部分。这并不是说应用程序不应该检查以及(没有点甚至发送例如一个无效的日期为datbase失败的插入)。由于有啊重新设计,我会把更多的时间和精力投入到设计必要的约束,并选择正确的数据类型(不存储日期作为例如字符串数据),比试图使非常普通的标准化结构看起来更优雅。

我会带来它在尽可能接近他们的模型尽可能(如果可能的话,我会得到满足他们的架构哪些文件 - 而不是扁平的版本)。如果你把数据直接导入你的模型中,如果数据发送他们开始打破转型假设您的内部应用程序的模型,会发生什么?

更好的把他们的数据,运行完整性检查,检查的假设不受侵犯。那么,如果你有一个应用程序特定的模型,将其转化为了最佳的使用你的应用程序。

不要反规范化。试图通过非规范化以acheive一个良好的架构设计就像是试图从纽约开车离开去旧金山。它不会告诉你走哪条路。

在你的情况,你想弄清楚一个规范化模式想什么。您可以基础,在很大程度上源模式,但你需要了解哪些数据的函数依赖(FD)是。既不源模式也不是平坦的文件都保证所有的FD透露给你。

一旦你知道一个标准化的模式将是什么样子,你现在需要弄清楚如何设计出满足您需求的架构。据该模式比完全正常化稍差,就这样吧。但是要在你的desgined架构的扁平文件中的数据和数据之间的转换编程困难准备。

您说,您的公司以前的模式由于成本不一致和不准确百万。更标准化的模式是,更多的保护,你是从内部不一致。这可让您自由保持高度警惕不准确。这就是始终如一地错一致的数据可以是作为不一致的数据作为具有误导性。

为您的店面(或不管它是你正在构建,对不太清楚)总是会使用来自该供应商的数据?您也许更换供应商或添加其他不同供应商?

如果这样,设计出满足的的需求的一般模式,和供应商数据映射到它。个人而言,我宁愿遭受自引用类(分层)表(难以置信的未成年人)“痛”比维持四(显然是半没用)范畴变种的水平,然后明年找出他们已经增加了5,或引入产品线只有三个...

对我来说,真正的问题是: 什么更适合模型?

这就像比较元组和列表。

  1. 元组是固定大小的并且是异构的——它们是“超规范化的”。
  2. 列表的大小是任意的并且是同质的。

当我需要元组时我使用元组,当我需要列表时我使用列表;它们从根本上服务于不同的目的。

在这种情况下,由于 产品结构已经明确 (我认为不太可能改变)那么我会坚持使用“元组方法”。 列表(或递归表模式)的真正威力/用途是当您需要它时 扩张 任意深度,例如 BOM 或谱系树。

我根据需要在一些数据库中使用这两种方法。 然而,递归模式也有一个“隐藏成本”,即并非所有 ORM(不确定 AR)都很好地支持它。许多现代数据库都支持“连接”(Oracle)、层次结构 ID (SQL Server) 或其他递归模式。另一种方法是使用基于集合的层次结构(通常依赖于触发器/维护)。无论如何,如果使用的 ORM 不能很好地支持递归查询,那么直接使用数据库功能可能会产生额外的“成本”——无论是在手动查询/视图生成方面还是在触发器等管理方面。如果您不使用时髦的 ORM,或者只是使用 iBatis 等逻辑分隔符,那么这个问题甚至可能不适用。

就性能而言,在新的 Oracle 或 SQL Server(以及可能的其他)RDBMS 上,它应该非常具有可比性,因此这是我最不用担心的:但请查看可用于解决您的 RDBMS 和可移植性问题的解决方案。

大家谁建议你不要在数据库中引入了一个层次,考虑具有自引用的表的只是选择。这不是在数据库中的层次结构模型的唯一途径。 您可以使用不同的方法,它为您提供更加方便快捷的查询,而无需使用递归查询。 比方说,你在你的层次结构有一个大集的节点(类别):

  

SET1 =(节点1节点2节点3 ...)

在此集中的任何节点也可以彼此通过自身设置,包含其它节点或嵌套集合:

  

节点1 =(节点2节点3 =(节点4节点5 =(Node6)Node7))

现在,我们如何可以模拟?让我们每个节点具有两个属性,即设置包含的节点的边界:

  

节点= {ID:整数,最小值:INT,最大:INT}

为了模拟我们的层次,我们只需相应分配这些最小值/最大值:

  

节点1 = {ID = 1,最小= 1,最大值= 10},点击   节点2 = {ID = 2,最小= 2,最大值= 2}点击   节点3 = {ID = 3,最小= 3,最大值= 9},点击   节点4 = {ID = 4,最小= 4,最大值= 4}点击   节点5 = {ID = 5,最小值= 5,最大值= 7},点击   Node6 = {ID = 6,最小= 6,最大= 6}结果   Node7 = {ID = 7,最小值= 8,最大值= 8}结果

现在,来查询下设置/节点5的所有节点:

  

选择不适用。*从节点为n,节点为s,点击   其中s.Id = 5和s.Min

在仅消耗资源的操作是,如果你要插入一个新的节点,或在层次结构中移动的一些节点,因为很多记录会受到影响,但是这是好的,作为层次结构本身不会经常变化。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top