让我们将讨论过的加载方法付诸实践。通过演练一些常见情况,您将更好地理解如何选择合适的加载策略并预见潜在问题。请记住,加载阶段的目标是稳定地将转换后的数据载入目标系统,以供使用。场景一:首次大规模加载想象您的团队正在搭建一个全新的数据仓库,用于分析销售业绩。您有几年来的历史销售数据,这些数据已从旧系统中提取并转换成整洁的CSV文件。数据仓库中的目标表,我们姑且称之为FactSales,目前完全是空的。问题: 哪种加载策略在这里最合理:全量加载($L_{full}$)还是增量加载($L_{incremental}$)?为什么?考量: 在开始加载之前,您必须确认关于FactSales表和您已转换的CSV数据哪些方面?思路分析: 由于FactSales表是空的,并且您希望用所有已准备好的历史数据来填充它,因此完全填充该表是目标。增量加载不合理,因为没有现有内容可供更新或添加。回答: 全量加载($L_{full}$)是适合的策略。它旨在加载整个数据集,通常涉及先清空(截断)目标表(尽管在这种情况下,目标表已经是空的),然后插入所有转换后的记录。加载前,有几点非常重要:验证目标表结构: 确保FactSales表的结构(列、数据类型、约束)与您转换后的数据结构匹配。确认表结构映射: 仔细检查CSV文件中的每列是否正确映射到FactSales表中的预期列。场景二:每日销售更新初始加载成功了!现在,您的数据仓库包含了历史销售数据。今后,每天早上,您的ETL过程只提取前一天的销售交易。这些新数据需要添加到FactSales表中,而不影响现有的历史记录。问题: 对于这些每日更新,您应该使用全量加载还是增量加载?考量: 如果使用增量方法,您主要是添加新数据还是更改现有数据?哪条信息对于确保您不会意外加载同一天的销售数据两次来说非常重要?思路分析: 每天进行全量加载效率极低。它将涉及删除所有现有数据并重新加载所有内容,包括未更改的历史数据,只为添加一天的交易数据。您只想添加新记录。回答: 增量加载($L_{incremental}$)是正确的方法。具体来说,由于这些是前一天完全新的交易,因此追加策略(一种增量加载类型)最适合。您只是简单地向FactSales表添加新行。为了防止重复,您需要一种方法来识别已加载的记录。这通常涉及跟踪加载日期或使用交易日期本身。您的ETL过程需要逻辑来确保它只处理应处理的特定前一天的记录。场景三:更新产品信息您的数据仓库还包含一个DimProduct表,其中包含每个已售产品的详细信息(ID、名称、类别、价格)。偶尔地,源系统中现有产品的信息会发生变化(例如,价格更新、类别更改)。您的ETL过程会提取一个文件,其中只包含有更改的产品,通过其唯一的ProductID识别。问题: 这里需要哪种加载策略?考量: 如果传入文件中的ProductID与现有产品匹配,DimProduct表中应该发生什么?如果ProductID是全新的(这可能表明数据质量问题或确实是新产品)怎么办?思路分析: 就像每日销售一样,您不希望每次只更改几个价格就重新加载整个产品维度表。然而,与每日销售不同的是,您不仅仅是添加新记录;您需要修改现有记录。回答: 这需要增量加载($L_{incremental}$),特别是处理更新的(通常称为“更新插入”或“合并”操作)。如果传入的ProductID与DimProduct中的现有行匹配,加载过程应该用新信息(例如,新价格)更新该行。如果传入的ProductID在DimProduct中不存在,您需要一个明确的业务规则。常见方法是:插入: 将新产品作为新行添加(追加)。拒绝/记录: 丢弃该记录并记录错误,因为意外的新产品可能表明上游存在问题。这种更新/插入逻辑是维度表加载中的常见模式。场景四:处理加载错误让我们回顾一下每日销售加载(场景二)。FactSales表要求日期为YYYY-MM-DD格式。然而,在今天的加载过程中,源文件中的几行错误地将日期格式化为MM/DD/YYYY。您的转换逻辑没有发现这个问题。问题: 当加载过程尝试将包含'05/20/2024'的行插入到预期为'2024-05-20'日期格式的列时,可能会发生什么?考量: 加载过程可以如何配置来处理此类错误?思路分析: 数据库和数据仓库会强制执行数据类型。尝试插入不符合目标列预期格式的文本(例如将'MM/DD/YYYY'放入严格的日期类型)通常会导致问题。回答: 加载过程那些特定的行很可能失败。数据库将拒绝插入,因为提供的字符串'05/20/2024'无法隐式转换为所需的YYYY-MM-DD日期格式。整体加载行为取决于其配置:遇到第一个错误时停止: 一旦遇到第一个错误记录,整个加载过程可能会停止。拒绝并继续: 过程可以配置为跳过导致错误的行,将它们记录到错误文件或表中,并继续加载有效记录。先加载所有,稍后验证: 对于类型错误较不常见,某些系统可能会将数据加载到具有更灵活类型的中转表,依靠加载后的验证来发现问题(尽管类型不匹配通常更早被发现)。对于初级数据管道,记录错误并决定是停止还是继续加载有效记录是一个常见要求。理想情况下,此类数据格式问题应在转换阶段捕获并纠正,在尝试加载之前。练习:源到目标的映射想象您的转换后的数据如下(简化):源字段:transaction_id、sale_timestamp、product_identifier、units_sold、revenue_usd您的目标表FactSales具有以下结构:目标列:SalesKey(自动递增整数)、TransactionID(varchar)、DateKey(整数,链接到DimDate表)、ProductKey(整数,链接到DimProduct表)、QuantitySold(整数)、Revenue(decimal)假设您的转换阶段已通过查找处理了将sale_timestamp转换为DateKey以及将product_identifier转换为ProductKey。任务: 在加载过程中,您将如何把源字段映射到目标列?digraph G { rankdir=LR; node [shape=record, style=filled, fillcolor="#e9ecef"]; edge [color="#495057"]; source [label="{源数据| \ <f0> transaction_id | \ <f1> sale_timestamp (用于DateKey查找) | \ <f2> product_identifier (用于ProductKey查找) | \ <f3> units_sold | \ <f4> revenue_usd \ }"]; target [label="{目标:FactSales| \ <t0> SalesKey (自动生成) | \ <t1> TransactionID | \ <t2> DateKey (来自查找) | \ <t3> ProductKey (来自查找) | \ <t4> QuantitySold | \ <t5> Revenue \ }"]; source:f0 -> target:t1 [label=" 映射"]; source:f1 -> target:t2 [label=" 查找并映射"]; source:f2 -> target:t3 [label=" 查找并映射"]; source:f3 -> target:t4 [label=" 映射"]; source:f4 -> target:t5 [label=" 映射"]; }一张图表,显示了从源字段到目标表列的映射。SalesKey由数据库生成,而DateKey和ProductKey假定在加载前的转换阶段派生。映射:transaction_id -> TransactionIDsale_timestamp(已转换) -> DateKeyproduct_identifier(已转换) -> ProductKeyunits_sold -> QuantitySoldrevenue_usd -> RevenueSalesKey通常在插入时由数据库自动生成,因此不需要从源文件直接映射。通过演练这些场景,您将明白理解数据特性(初始与持续、新增与更新)以及目标系统,对于选择正确的加载策略以及预见模式映射和错误处理等必要步骤是多么根本。