敏捷 DWH 设计方法概述

开发存储设施是一项长期而艰巨的任务。

项目的生命周期在很大程度上取决于对象模型和基础结构在开始时的考虑程度。

普遍接受的方法一直是并且仍然是星型方案与第三范式相结合的各种变体。 通常,根据原则:初始数据 - 3NF,展示 - 明星。 这种经过时间考验并得到大量研究支持的方法是经验丰富的 DWH 专家在考虑分析存储库应该是什么样子时首先想到的(有时是唯一的)事情。

另一方面,一般业务和特别是客户需求往往会快速变化,数据往往会“深度”和“广度”增长。 这就是明星的主要缺点出现的地方——有限 灵活性.

如果在您作为 DWH 开发人员的安静舒适的生活中突然出现:

  • 任务是“至少快速做一些事情,然后我们看看”;
  • 出现了一个快速发展的项目,每周至少一次连接新资源并重新设计商业模式;
  • 出现了一位客户,他不知道系统应该是什么样子以及它最终应该执行什么功能,但准备好进行试验并不断完善所需的结果,同时不断接近它;
  • 项目经理顺便带来了好消息:“现在我们有了敏捷!”

或者,如果您只是想了解如何构建存储设施 - 欢迎来到剪切!

敏捷 DWH 设计方法概述

“灵活性”是什么意思?

首先,让我们定义一个系统必须具备哪些属性才能被称为“灵活”。

另外,值得一提的是,所描述的属性应具体涉及 系统, 不 过程 它的发展。 因此,如果您想了解敏捷作为一种开发方法,最好阅读其他文章。 例如,就在那里,在 Habré 上,有很多有趣的材料(比如 审查 и 实用有问题的).

这并不意味着开发过程和数据仓库的结构完全无关。 总的来说,为敏捷架构开发敏捷存储库应该要容易得多。 然而,在实践中,根据 Kimbal 和 DataVault 的说法,经典 DWH 的敏捷开发通常有多种选择 - 根据 Waterfall 的说法,而不是一个项目上两种形式的灵活性的巧合。

那么,灵活存储应该具备哪些能力呢? 这里有三点:

  1. 提前交付和快速周转 - 这意味着理想情况下应尽早获得第一个业务结果(例如第一个工作报告),即甚至在整个系统完全设计和实施之前。 而且,后续的每次修改也应该花费尽可能少的时间。
  2. 迭代细化 - 这意味着每次后续改进理想情况下不应影响已经运行的功能。 这一刻往往成为大型项目中最大的噩梦 - 迟早,各个对象开始获得如此多的连接,以至于在附近的副本中完全重复逻辑比向现有表添加字段更容易。 如果您惊讶地发现分析改进对现有对象的影响可能比改进本身花费更多的时间,那么您很可能还没有使用过银行或电信中的大型数据仓库。
  3. 不断适应不断变化的业务需求 - 整体对象结构的设计不应仅考虑可能的扩展,而是应预期下一次扩展的方向在设计阶段是无法想象的。

是的,在一个系统中满足所有这些要求是可能的(当然,在某些情况下并且有一些保留)。

下面我将考虑两种最流行的数据仓库敏捷设计方法 - 锚模型 и 资料库。 排除在括号之外的是一些优秀的技术,例如 EAV、6NF(以其纯粹的形式)以及与 NoSQL 解决方案相关的所有内容 - 并不是因为它们在某种程度上更糟糕,甚至不是因为在这种情况下该文章会威胁要收购平均disser的音量。 只是所有这些都与稍微不同类别的解决方案相关 - 要么是可以在特定情况下使用的技术,无论项目的整体架构如何(例如 EAV),要么是全局其他信息存储范例(例如图形数据库)和其他选项 NoSQL)。

“经典”方法的问题及其灵活方法的解决方案

我所说的“经典”方法是指优秀的老明星(无论底层的具体实现如何,请 Kimball、Inmon 和 CDM 的追随者原谅我)。

1. 连接的刚性基数

该模型基于将数据明确划分为 方面 и 事实。 这,妈的,是合乎逻辑的——毕竟,绝大多数情况下的数据分析都归结为对某些部分(维度)中某些数值指标(事实)的分析。

在这种情况下,对象之间的连接是使用外键以表之间关系的形式建立的。 这看起来很自然,但立即导致了灵活性的第一个限制—— 严格定义连接基数.

这意味着在表设计阶段,您必须准确确定每对相关对象是否可以多对多关联,还是只能一对多关联,以及“在哪个方向”。 这直接决定了哪个表将具有主键,哪个表将具有外键。 当收到新要求时改变这种态度很可能会导致基础的重新设计。

例如,在设计“现金收据”对象时,您依靠销售部门的誓言,制定了行动的可能性 一次晋升多个检查职位 (但反之则不然):

敏捷 DWH 设计方法概述
一段时间后,同事们推出了一种新的营销策略,他们可以在相同的位置上采取行动 多个促销活动同时进行。 现在您需要通过将关系分离到单独的对象中来修改表。

(现在加入升级检查的所有派生对象也需要改进)。

敏捷 DWH 设计方法概述
Data Vault 和锚定模型中的关系

事实证明,避免这种情况非常简单:您不必相信销售部门会这样做。 所有连接最初都存储在单独的表中 并将其处理为多对多。

提出了这种方法 丹·林斯特 作为范式的一部分 资料库 并全力支持 拉尔斯·伦巴克 в 锚模型.

由此,我们得到了灵活方法论的第一个显着特征:

对象之间的关系不存储在父实体的属性中,而是单独类型的对象。

В 资料库 这种链接表称为 链接而在 锚模型 - 领带。 乍一看,它们非常相似,尽管它们的差异并不以名称结束(这将在下面讨论)。 在两种架构中,链接表都可以链接 任意数量的实体 (不一定是 2)。

乍一看,这种冗余为修改提供了极大的灵活性。 这样的结构不仅可以容忍现有链接基数的变化,还可以容忍新链接的添加 - 如果现在支票位置也有一个指向突破它的收银员的链接,那么这种链接的出现将简单地成为现有表的附加组件,而不影响任何现有对象和流程。

敏捷 DWH 设计方法概述

2. 数据重复

灵活架构解决的第二个问题不太明显,并且是首先固有的。 SCD2 型测量 (慢慢改变第二种类型的维度),尽管不仅仅是他们。

在经典仓库中,维度通常是一个表,其中包含代理键(作为 PK)以及单独列中的一组业务键和属性。

敏捷 DWH 设计方法概述

如果维度支持版本控制,则版本有效性边界将添加到标准字段集,并且源中一行的多个版本会出现在存储库中(版本化属性的每个更改对应一个版本)。

如果一个维度至少包含一个频繁更改的版本化属性,那么该维度的版本数量将是可观的(即使其余属性没有版本化或从不更改),并且如果存在多个这样的属性,则版本数量可以他们的数量呈指数级增长。 该维度可能会占用大量磁盘空间,尽管它存储的大部分数据只是其他行中不可变属性值的重复。

敏捷 DWH 设计方法概述

同时,它也经常被使用 非规范化 — 某些属性有意存储为值,而不是作为参考书或其他维度的链接。 此方法可加快数据访问速度,减少访问维度时的联接数量。

通常这会导致 相同的信息同时存储在多个地方。 例如,有关居住地区和客户类别的信息可以同时存储在“客户”维度和“购买”、“送货”和“呼叫中心呼叫”事实中,以及“客户-客户经理”中”链接表。

一般来说,上述内容适用于常规(非版本化)维度,但在版本化维度中,它们可能具有不同的比例:对象新版本的出现(尤其是回顾起来)不仅会导致所有相关的更新表,而是相关对象的新版本的级联出现 - 当表 1 用于构建表 2,表 2 用于构建表 3 时,等等。 即使表 1 的构造中不涉及表 3 的单个属性(并且涉及从其他来源获得的表 2 的其他属性),对该构造进行版本控制至少会导致额外的开销,最多会导致额外的开销。表 3 中的版本与它完全无关,并且在链的更下游。

敏捷 DWH 设计方法概述

3.返工的非线性复杂性

同时,每个建立在另一个店面基础上的新店面都会增加在 ETL 发生更改时数据可能“发散”的地方的数量。 这反过来又导致每个后续修订的复杂性(和持续时间)增加。

如果上面描述的系统很少修改 ETL 过程,那么您可以生活在这样的范例中 - 您只需要确保对所有相关对象进行正确的新修改。 如果频繁进行修改,则意外“丢失”多个连接的可能性会显着增加。

此外,如果我们考虑到“版本化”ETL 比“非版本化”ETL 复杂得多,那么在频繁更新整个设施时就很难避免错误。

在 Data Vault 和 Anchor Model 中存储对象和属性

灵活架构的作者提出的方法可以表述如下:

有必要将变化的内容与保持不变的内容区分开来。 也就是说,将键与属性分开存储。

然而,人们不应该混淆 没有版本控制 属性与 不变:第一个不存储其更改的历史记录,但可以更改(例如,当更正输入错误或接收新数据时);第二个永远不会更改。

对于数据仓库和锚模型中到底什么可以被认为是不可变的,存在不同的观点。

从建筑学的角度来看 资料库, 可以认为是不变的 整套钥匙 - 自然(组织的 TIN、源系统中的产品代码等)和替代。 在这种情况下,剩余的属性可以根据变化的来源和/或频率进行分组,并且 为每个组维护一个单独的表 具有一组独立的版本。

在范式中 锚模型 视为不变 唯一的代理键 本质。 其他一切(包括自然键)只是其属性的特例。 其中 默认情况下所有属性都是相互独立的,因此对于每个属性 单独的表.

В 资料库 包含实体键的表称为 胡巴米。 集线器始终包含一组固定的字段:

  • 自然实体键
  • 代理键
  • 链接到来源
  • 记录添加时间

中心的帖子 永远不会改变并且没有版本。 从外部来看,集线器与某些系统中用于生成代理项的 ID 映射类型表非常相似,但是,建议使用一组业务密钥中的哈希值作为 Data Vault 中的代理项。 这种方法简化了从源加载关系和属性(不需要加入集线器来获取代理,只需计算自然键的哈希值),但可能会导致其他问题(例如,与冲突、大小写和不可打印相关)字符串键等中的字符.p.),因此它不被普遍接受。

所有其他实体属性都存储在称为 卫星。 一个集线器可以有多个存储不同属性集的卫星。

敏捷 DWH 设计方法概述

卫星之间的属性分配遵循以下原则 共同改变 — 在一颗卫星中,可以存储非版本化属性(例如,个人的出生日期和 SNILS),在另一颗卫星中,存储很少更改的版本化属性(例如,姓氏和护照号码),在第三颗卫星中,存储经常更改的属性(例如,送货地址、类别、最后订单日期等)。 在这种情况下,版本控制是在单个卫星级别进行的,而不是在整个实体级别上进行的,因此建议分发属性,以使一颗卫星内版本的交集最小化(这会减少存储版本的总数) )。

此外,为了优化数据加载过程,从各种来源获得的属性通常包含在各个卫星中。

卫星通过以下方式与集线器通信 外键 (对应于一对多基数)。 这意味着这种“默认”架构支持多个属性值(例如,一个客户的多个联系电话号码)。

В 锚模型 存储键的表称为 。 他们保留:

  • 仅代理键
  • 链接到来源
  • 记录添加时间

从锚模型的角度考虑自然键 普通属性。 此选项可能看起来更难以理解,但它为识别对象提供了更大的范围。

敏捷 DWH 设计方法概述

例如,如果有关同一实体的数据可以来自不同的系统,每个系统都使用自己的自然密钥。 在 Data Vault 中,这可能会导致多个集线器的结构相当繁琐(每个源一个 + 统一的主版本),而在 Anchor 模型中,每个源的自然键属于其自己的属性,并且可以在独立加载时使用所有其他人。

但这里也有一个阴险的地方:如果来自不同系统的属性组合在一个实体中,很可能存在一些属性 “粘合”规则,系统必须了解来自不同来源的记录对应于实体的一个实例。

В 资料库 这些规则很可能决定阵型 主实体的“代理中心” 并且不会以任何方式影响存储自然源密钥及其原始属性的集线器。 如果在某个时刻合并规则发生变化(或者执行合并规则的属性被更新),则重新格式化代理集线器就足够了。

В 锚模型 这样的实体很可能存储在 唯一的锚。 这意味着所有属性,无论它们来自什么来源,都将绑定到同一个代理。 分离错误合并的记录以及一般情况下监视此类系统中合并的相关性可能要困难得多,特别是如果规则非常复杂且频繁更改,并且可以从不同的源获取相同的属性(尽管它肯定是可能的,因为每个属性版本都保留其源的链接)。

无论如何,如果您的系统应该实现该功能 重复数据删除、合并记录和其他 MDM 元素,值得特别关注敏捷方法中存储自然键的方面。 就合并错误而言,笨重的数据仓库设计可能会突然变得更安全。

锚模型 还提供了一个额外的对象类型,称为 它本质上很特别 简并型锚点,它只能包含一个属性。 这些节点应该用于存储平面目录(例如性别、婚姻状况、客户服务类别等)。 与锚不同的是,结 没有关联的属性表,并且它的唯一属性(名称)始终与键存储在同一个表中。 节点通过连接表(Tie)连接到 Anchor,就像 Anchor 之间相互连接一样。

关于节点的使用没有明确的意见。 例如, 尼古拉·戈洛夫在俄罗斯积极推广使用锚定模型的人认为(并非没有道理),没有一本参考书可以肯定地说,它 всегда 将是静态的和单级的,因此最好立即对所有对象使用成熟的 Anchor。

Data Vault 和 Anchor 模型之间的另一个重要区别是可用性 连接属性:

В 资料库 链接是与集线器相同的成熟对象,并且可以具有 自己的属性。 在 锚模型 链接仅用于连接锚点和 不能有自己的属性。 这种差异导致建模方法显着不同 事实,这将进一步讨论。

事实存储

在此之前,我们主要讨论了测量建模。 事实还不太清楚。

В 资料库 存储事实的典型对象是 关联,在其卫星中添加真实指标。

这种方法看起来很直观。 它提供了对分析指标的轻松访问,通常类似于传统的事实表(只是指标不存储在表本身中,而是存储在“相邻”表中)。 但也存在陷阱:模型的典型修改之一 - 事实密钥的扩展 - 需要 向 Link 添加新的外键。 反过来,这“破坏”了模块化并可能导致需要修改其他对象。

В 锚模型 连接不能有自己的属性,因此这种方法行不通——所有属性和指标绝对必须链接到一个特定的锚点。 由此得出的结论很简单—— 每个事实也需要自己的锚点。 对于我们习惯于视为事实的某些内容,这可能看起来很自然 - 例如,购买的事实可以完美地简化为对象“订单”或“收据”、访问网站进行会话等。 但也有一些事实,要找到这样一个天然的“载体对象”并不那么容易——例如,每天早上仓库中剩余的货物。

因此,在 Anchor 模型中扩展事实键时不会出现模块化问题(只需向相应的 Anchor 添加新的关系就足够了),但设计一个模型来显示事实就不那么明确了;可能会出现“人工”Anchor以不清楚的方式显示业务对象模型。

如何实现灵活性

两种情况下得到的结构都包含 明显更多的桌子比传统测量。 但这可能需要 显着减少磁盘空间 具有与传统维度相同的版本化属性集。 当然,这里并没有什么魔力——一切都与标准化有关。 通过跨卫星(在数据仓库中)或单个表(锚模型)分配属性,我们减少(或完全消除) 更改其他属性时某些属性的值重复.

资料库 奖金将取决于卫星之间的属性分布,并且 锚模型 — 几乎与每个测量对象的平均版本数成正比。

然而,节省空间是单独存储属性的一个重要优势,但不是主要优势。 与单独的关系存储一起,这种方法使得存储 模块化设计。 这意味着在这样的模型中添加单独的属性和整个新的主题领域看起来像 上层建筑 覆盖现有的一组对象而不更改它们。 这正是所描述的方法变得灵活的原因。

这也类似于从单件生产到大规模生产的转变——如果在传统方法中模型的每个表都是唯一的并且需要特别关注,那么在灵活的方法中它已经是一组标准“零件”。 一方面,表更多,加载和检索数据的过程应该看起来更复杂。 另一方面,他们也成为 典型的。 这意味着可能有 自动化和元数据驱动。 “我们将如何铺设?”这个问题的答案可能会占用设计改进工作的很大一部分,但现在根本不值得(以及关于更改模型对工作流程的影响的问题) )。

这并不意味着这样的系统根本不需要分析师——仍然需要有人处理具有属性的对象集,并弄清楚在哪里以及如何加载它们。 但工作量以及出错的可能性和成本都显着减少。 无论是在分析阶段还是在 ETL 的开发过程中,其中很大一部分都可以简化为编辑元数据。

黑暗的一面

所有这些使得这两种方法真正灵活、技术先进并且适合迭代改进。 当然,还有一个“美中不足”,我想你已经猜到了。

数据分解是灵活架构模块化的基础,导致表数量增加,相应地, 高架 采样时加入。 为了简单地获取一个维度的所有属性,在经典存储中,一个选择就足够了,但灵活的架构将需要一系列的连接。 而且,如果所有这些报表的连接都可以提前编写,那么习惯于手工编写SQL的分析师将遭受加倍的痛苦。

有几个事实可以使这种情况变得更容易:

当处理大维度时,它的所有属性几乎不会同时使用。 这意味着连接数可能比模型乍一看要少。 在向卫星分配属性时,Data Vault 还可以考虑预期的共享频率。 同时,集线器或锚点本身主要用于在加载阶段生成和映射代理,并且很少在查询中使用(对于锚点尤其如此)。

所有连接都是通过键进行的。 此外,更加“压缩”的数据存储方式减少了在需要时扫描表的开销(例如,按属性值过滤时)。 这可能导致这样一个事实:从具有一堆联接的规范化数据库中进行采样甚至比扫描每行多个版本的一个大维度更快。

例如,在这里 文章包含了 Anchor 模型性能与一张表中样本的详细对比测试。

很大程度上取决于发动机。 许多现代平台都有内部连接优化机制。 例如,MS SQL 和 Oracle 可以“跳过”表的联接,如果它们的数据除了其他联接之外没有在任何地方使用,并且不影响最终选择(表/联接消除),而 MPP Vertica Avito 同事的经验,已被证明是锚模型的优秀引擎,考虑到对查询计划的一些手动优化。 另一方面,将锚定模型存储在例如具有有限连接支持的 Click House 上,看起来还不是一个好主意。

此外,对于这两种架构都有 特殊动作,使数据访问更容易(无论是从查询性能的角度还是对于最终用户而言)。 例如, 时间点表 在数据保险库中或 特殊表函数 在锚模型中。

在总

所考虑的灵活架构的主要本质是其“设计”的模块化。

正是这个属性允许:

  • 经过一些与元数据部署和编写基本 ETL 算法相关的初步准备后, 快速向客户提供第一个结果 以包含来自几个源对象的数据的几个报告的形式。 没有必要彻底思考(即使是在顶层)整个对象模型。
  • 数据模型只需 2-3 个对象就可以开始工作(并且有用),然后 逐渐成长 (关于锚模型尼古拉 应用的 与菌丝体进行了很好的比较)。
  • 大多数改进,包括扩展主题领域和添加新来源 不会影响现有功能,也不会带来破坏已经运行的功能的风险.
  • 由于分解为标准元素,此类系统中的 ETL 流程看起来相同,它们的编写方式适合算法化,最终, 自动化.

这种灵活性的代价是 生产率。 这并不意味着在此类模型上不可能实现可接受的性能。 通常,您可能只是需要更多的努力和对细节的关注来实现您想要的指标。

应用

实体类型 资料库

敏捷 DWH 设计方法概述

有关数据保险库的更多信息:
丹·利斯塔特的网站
关于 Data Vault 的所有信息(俄语)
关于 Habré 上的 Data Vault

实体类型 锚模型

敏捷 DWH 设计方法概述

有关锚定模型的更多详细信息:

Anchor Model 创作者的网站
关于在 Avito 中实现 Anchor 模型的经验的文章

所考虑方法的共同特征和差异的汇总表:

敏捷 DWH 设计方法概述

来源: habr.com

添加评论