数据仓库ETl工具箱6

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

提交事实表事实表装有企业的度量数据。事实表与度量的关系非常简单。如果存在一个度量,则它可以被模型化为事实表的行。如果事实表的行存在,则它就是一个度量。那么什么是度量呢?一个关于度量通用的定义是:通过工具或比例等级可以测量观察的数量值。在维度建模时,我们有意识地围绕企业的数字度量创建我们的数据库。事实表包含度量,维表包含关于度量的上下文。这种关于事物的简单视图被一次又一次的证明是昀终用户直观理解我们的数据仓库的方式。这也是我们为什么通过维度模型打包和提交数据仓库内容的原因。流程检查规划与设计:需求/现状-架构-实现-测试/发布数据流:抽取-清洗-规格化-提交第5章描述了如何创建数据仓库的维表。也许从维表开始介绍会觉得很奇怪,因为度量以及事实表才是昀终用户真正想要看的内容,但是维表是事实表数据的入口,事实只有通过维度解释才会变得有意义。由于第5章详细完整地描述了维,因此本章的内容多少会变得简单一些。事实表基本结构每一个事实表通过表的粒度来定义。事实表的粒度是事件度量的定义。设计者必须至始至终按照度量如何在现实世界中理解来规定事实表的粒度。例如,图6.1中的事实表的粒度为指定的零售发票上的单个货品。我们并不从定义这些字段的粒度开始,而是将粒度表示成为维度的外键和事实表的某些字段。粒度定义必须按照现实的,物理的度量意义来定义,然后才考虑维度和事实表中的其他字段等其他因素。所有的事实表包含了一组关联到维表的外键,而这些维表提供了事实表度量的上下文。大多数的事实表还包括了一个或者多个数值型的度量字段,我们称之为事实(Fact)。请看图6.1。某些事实表中还包还了一个或者多个特殊的近似维度字段,他们是在第5章中介绍的退化维度(DegenerateDimensions)。退化维度存在于事实表,但是他们不是外键,不关联任何真正的维表。我们在图6.1中使用符号DD来标识退化维度。图6.1昀细粒度的销售交易事实表在现实实践中,事实表一般都至少包含3个维度,而且绝大多数包含更多的维度。由于过去的20年中,随着数据仓库以及相应的软、硬件技术的成熟,事实表技术有了很大的提高,可以存储越来越多的昀细粒度上量测值。越来越少的度量,越来越多的维度。在昀初的零售销售数据仓库中,数据集仅仅是粗粒度的聚合值。这些早期的零售数据仓库通常只有3到4个维度(产品、市场、时间和促销)。现在,我们搜集销售交易的原子级别的零售数据。一个单独的销售交易中很轻易就包含了图6.1中的10个维度(日历日;产品;商店级别的现金帐簿;客户;员工;商店经理;价格范围;促销折扣;交易类型和付款方式)。更多的时候我们还要在目前的基础上增加新的维度:比如商店人口统计学指标,市场竞争事件和天气!事实上,每个事实表都包含一组由表中的字段定义的主键。在图6.1中,事实表一个可能的主键是由两个退化维度:发票号(Ticketnumber)和行号(LineNumber)组成的联合键。这两个字段唯一的定义了出纳登记簿cashierregister上的单个商品的度量事件。另外一个可能的等价主键是时间戳和出纳登记簿cashierregister的组合。如果在设计的时候没有給于足够的注意,那么就可能违反事实表上主键的假设:可能在同一个时段两个同样的度量事件会发生,但是数据仓库团队却没有意识到这一点。显然,每个事实表应该拥有一个主键,即使仅仅是出于管理的需要也应该在事实表设立主键。如果没有主键完整性,那么事实表中有可能存在两个或者更多一样的记录,而且没有办法按照独立的量测事件来区分他们。但是只要ETL团队保证单独的数据装载合理地表示唯一的量测事件,通过在装载时为数据增加唯一的序号就可以在事实表中唯一标识记录。尽管唯一的序号和业务没有关联,而且不应该发布给昀终用户,但是它在管理上保证了一个单独和可能的量测的发生。如果ETL团队不能够保证单独加载表示的是合法的独立的量测事件,那么在数据加载的时候数据上必须已经正确的定义了主键。前面的例子表明需要所有的ETL作业可以在发布或者发生错误时有再次运行的能力,以保证不会错误的更新目标数据库。在SQL语法中,更新不变化的值通常是安全的,但是更新增量的值是危险的。如果主键已经强制定义,那么插入是安全的,因为插入重复的值会触发错误。如果限制是基于简单字段值,那么通常来说删除也是安全的。确保参照完整性在维度模型中,参照完整性意味着事实表中的每个字段使用的是合法的外键。换句话说,没有事实表记录包含了被破坏的或者未知的外键参照。在维度模型中可能有两种情况会导致违反参照完整性:1.加载包含了错误外键的事实表记录2.删除了维表记录,而其主键在事实表中被使用。如果没有注意参照完整性,那么就会非常容易破坏它。笔者曾经研究了很多没有严格保证参照完整性的事实表;每个案例中都能够发现严重的冲突。一个事实表记录违反参照完整性(记录中包含一个或者多个外键)不仅仅是讨厌,更严重的是这非常危险。推想一下,一条合理的记录正确的记录了量测事件,但是不正确的存储在数据库中。任何使用了坏维度的事实表查询将不能包含该记录,因为按照定义,维表和该事实表记录的关联不会发生。但是在动态聚合中忽略该坏维度的查询结果却包含了这条记录。在图6.2中,我们显示了在ETL过程中可以保证参照完整性的三个主要位置。图6.2强制参考完整性选择1在将事实数据加载到昀终表之前,仔细的审核和准备数据,在删除任何维表记录之前,仔细地审核2在每次事实表插入操作和每次维表删除操作动作发生时,使用数据库自己的参照完整性检查3加载后对事实表进行扫描检查,以发现和更正有问题的外键,解决参照完整性冲突。从实践角度来讲,第一个选择更加可行。在数据加载到事实表中昀后一步就是查找事实表记录中的自然外键,然后将他们替换成为维表中的代理键。这个过程将在下一节代理键环节中仔细地介绍。这个过程的核心是一个特殊的查找表,它包含了每一个外来的自然键所使用的代理键的值。如果这张表被正确的维护,那么事实表中的记录将满足参照完整性。同样在维表记录被删除的时候也需要尝试联结事实表和维表,只有在查询返回null的时候才能够删除该记录。第二种选择利用数据库的参照完整性来检查的方法虽然很自然,但是在批量的加载成千上万条甚至几百万条记录的时候效率太低。当然这只是一个软件技术的问题,如RebBrick数据库系统(现在IBM在销售)设计为在任何时候都维护参照完整性,它可以在1个小时内向事实表加载100万条记录,同时检查所有维度的参照完整性。第三种在数据库更新完成后检查参照完整性的方法在理论上可以发现所有的冲突,但是花费的代价可能惊人的高,对参照完整性的检查需要使用:selectf.product_keyfromfact_tablefwheref.product_keynotin(selectp.product_keyfromproduct_dimensionp)在拥有几百万行产品维度数据,以及数亿行事实表纪录的环境中,这是一个荒谬的查询。当然可以将查询仅仅限于当天加载的数据,但这需要假设时间维度的外键是正确的为前提。但是使用第一种选择时,这种方法可以作为一种额外的检查。代理键管道在建立事实表时,昀终的ETL步骤是将新数据记录的自然键转化成正确的、当期的代理键。在这节,我们假设所有的记录已经加载到事实表中。换句话说,我们需要使用为每个维度实体(如客户或者产品)使用当前的代理键。我们将在这章的昀后处理迟到的事实记录。我们理论上可以通过在每个维表中获取昀新的记录来为自然键获得当前的代理键,这在逻辑上是正确的,但是很慢。替代方法是为每一个维度维护一个专门的代理键查找表。这张表在新的维度实体创建的时候或者记录在发生类型2缓慢变化维度2的更新的时候被更新。我们在第5章讨论图5.16的时候介绍了这种表。维表在插入或者缓慢变化维度2更新发生之后,在处理事实表之前,这个维表必须被完全的更新。在更新事实表之前的维表更新过程是维护维表和事实表参照一致性的一般过程。反向的过程在删除记录的时候发生,首先我们删除不需要的事实表记录,然后删除不再联结到事实表的维度记录。不必因为事实表不再参照该记录而删除维表记录。即使事实表中没有引用该维度实体,维度实体也可能需要存在或者保存在维表中。当我们更新维表的时候,不仅仅要更新所有的维表记录,还要更新存储当期的数据仓库键和自然键关联关系的代理键查找表。图6.3代理键管道我们处理新增的事实表记录的过程非常容易理解。请看图6.3。我们从新增事实表记录中获得每个自然键键值,然后替换成对应的当期代理键。注意我们的提法:替换。我们在事实表记录中并不保存自然键。如果你关心具体的自然键值,你可以关联维表记录得到。如果你有4到12个自然键,每个新增的事实表记录需要4到12个单独的查找表来获得正确的代理键。首先,我们建立多线程的应用来流化所有的输入数据记录,使其通过图6.3中的所有步骤。这里的多线程,指的是记录#1在完成连续的键查找和替换的同时,#2在后面进行相应的处理,我们并不在第一个查找步骤中处理所有的新增记录,然后将整个文件交给下一步。在经过所有必要的处理过程后才将所有的记录写到磁盘意味着更高的效率。在处理过程中应该尽量充分使用内存。如果可能,所有需要的查找表应该常驻内存,以便每条事实表记录在处理它的自然键的时候随机访问。这是将查找表从原始数据仓库维表中分离的一个原因。假设对于某个维度,我们用上百万记录的查找表,如果自然键有20字节而代理键为4字节,我们需要24MB的内存来保存查找表。在使用4-8GB内存的机器作为数据准备机data-staging的环境中,我们可以非常容易在内存中加载所有的查找表。我们前面的讨论的架构是如何设计发挥昀大性能。如果你仅仅是每天加载几万条数据,而且装载窗口很大,那么你不需要强调这种级别的性能。你可以定义事实表和维表的星型联结,将自然键转化成代理键,用SQL处理整个过程。这种情况下,如果新增的数据不能匹配维度(参照完整性失败)你还可以对某些维度定义外联结。可以在这种环境中使用程序工具awk,因为他支持在内存中使用自然键作为下标建立Array来完成自然键到代理键的翻译。这样,如果你定义Translate_Dimension_A[natural_key]=surrogate_key,那么处理每一条事实表记录就非常简单:printTranslate_Dimension_A($1),Translate_Dimension_B($2)。在一些重要的大事实表中,你可能会遇到不寻常的monster维度,例如居民客户,可能拥有上亿条记录。如果我们只有一个这样的维度,那么我们仍然可以定义一个快速传递pipelined代理键系统,虽然这样巨大的维表在查找的时候会大量的读取磁盘。秘密在于按照维度的自然键对使用的事实表和查找表进行排序。这样,代理键替换变成了在两个文件之间一次性的按照顺序的合并。这个过程相当的快,尽管没有在内存中处理。如果你有两个这样的monster查找表在你的处理流程中pipeline中,而且不能在内存中处理,那么对于非排序的维度Key键上的随机访问所带来的I/O是难以承受的。由于在源系统中有可能没有参照完整性检查,这样对事实表记录进行代理键处理的时候要考虑处理一些无效的自然键。这种情况下,我们建议创建一个新的代理键,增加一条维表记录,标示为Unknown。如果无法对数据昀终更正,那么每个无效的自然键都应该给一个唯一的新的代理键。如果你的业务本身要求这些无效的自然键必须保持并且不被处理,那么在所有受到影响的维度中都只需要有一个单个的唯一的代理键(缺省的Unknown记录)。使用维表而不是查找表上一节介绍的查找表对于解决那些处理得事实表数据记录都是同阶段的,换句话说,都是当前的非常有效。如果有相当数量的事实记录延迟到达,那么查找表就不再适用,这时候必须使用维表作为正确的代理键的源。当然,这种假设的前提是维表的设计要遵循第5章的建议。避免使用独立的查找表还可以简化事实表加载之前的ETL管理工作,因为这种情况下不需要同步维表和查找表。某些ETL工具套件通过查找

1 / 31
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功