尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ETL与ELT的本质区别:从数据流程到团队协作的变革

ETL与ELT的本质区别:从数据流程到团队协作的变革 先讲一个我经常在数据团队里遇到的问题很多人会把 ETL 和 ELT 当成同一个流程的两种写法认为差别只是“转换”放在加载之前还是之后。实际在项目里跑过一段时间后才会意识到这两个词之间的差异根本不是字母顺序而是整个数据工作的起点、节奏和责任边界。如果从现代数据栈开始系统性讨论 ELT 算起这个概念已经站在“二十年”这个时间刻度附近了。回过头看ELT 真正改变的不是流水线上某个步骤的位置而是数据团队面对不确定需求时的应对方式。1. 先搞清楚 ELT 真正解决的是哪类问题1.1 传统 ETL 的流程和代价在数据仓库建设早期最常见的做法是 ETL先从源系统抽取数据在外部数据管道或中间层完成清洗、转换、合并再把加工好的结果加载到数据仓库。这个流程在业务稳定、报表需求明确的时候运行得非常好因为进入数仓的数据已经是“干净”的下游分析师拿到就能直接使用不太需要理解源系统字段的历史含义。但 ETL 的代价也很明确转换逻辑必须在数据进入数仓之前全部完成。这意味着建模需求要先于数据集成被定义清楚。一旦上游字段变了、业务口径变了或者分析团队发现需要一个之前没有保留的原始字段整个管道都要重新设计并重新回刷历史数据。更麻烦的是很多 ETL 工具是在专用服务器或调度集群上跑的它的计算能力有限能处理的往往是已经筛选过的、清洗过的数据而不是完整历史数据。早期这样做没有太大问题因为数据量不大业务变化也没那么快。但到了移动互联网、实时业务、用户行为分析大规模出现之后分析需求变得极其碎片化同一个订单数据市场部要按渠道切财务要按成本口径切风控要按用户维度切产品要看漏斗。如果每个部门的要求都要先经过 ETL 开发再排队等调度数据需求响应速度就会成为瓶颈。1.2 ELT 的关键变化把转换延后到仓内ELT 把顺序改成了抽取、加载、转换。更准确地说它先把源系统的原始数据快速复制到数据仓库或数据湖中等到真正需要做报表或训练模型时再在存储内部执行转换。这个变化看起来只是把 T 从中间挪到后面实际上解决了一个核心问题原始数据被完整保留了下来。因为转换发生在仓内数据团队不需要在一开始就决定“哪些字段有用、哪些字段无用”只需要决定“哪些数据需要接入”。字段级别的建模决策被延后了延后到真正理解业务需求的那一刻。用一句话概括ETL 是“先想清楚再接入”ELT 是“先接入再逐步想清楚”。后者更适合需求不确定、业务快速迭代的数据团队。1.3 为什么数据量变大之后ELT 变得更合理转换延后有一个前提存储和计算能力要足够强。早期数据仓库往往是专用一体机扩容成本极其昂贵不适合把所有原始数据都放进去。如果业务数据一天只有几十万行用 ETL 精细加工后再入仓是划算的因为存储和计算都能省下来。但现代数据仓库逐渐转向云原生架构存储和计算解耦扩容不再像过去那样需要提前申请硬件。MPP 架构的数据库可以把一个超大规模查询分布到上百个节点并行执行在仓内做转换的效率远高于在外部管道用单机或小集群处理。此时“先把原始数据加载进来”的成本变得很低而“在仓内按需查询和建模”的价值变得很高ELT 也就从一种边缘做法变成了主流方案。当然这不是说 ELT 完全取代 ETL。你可以把 ETL 看作一种在资源受限时代诞生的工程约束而 ELT 是计算和存储能力提升后把建模自由交回给数据消费者的一种新约束。1.4 对团队协作方式的影响很多人讨论 ELT 时只谈技术忽略了它对团队分工的改变。传统 ETL 模式下数据团队是加工方分析师是消费方。源系统字段含义、清洗逻辑、加工结果都集中在一部分人手里下游很难介入。ELT 模式下原始数据就在数仓里分析师和算法工程师只要能写 SQL就可以直接探索数据、先做临时查询再沉淀成正式模型。这减少了“提需求、等排期、看结果”的等待过程也让数据质量问题更早暴露。过去源系统字段脏可能要到管道处理失败才发现在 ELT 模式下加载完成的那一刻数据团队就可以开始检查数据分布和异常值。这也是为什么很多团队在迁移到 ELT 之后最大的感受不是“跑得快了”而是“协作方式变了”。2. ELT 的二十年从临时脚本到现代数据栈2.1 早期数据仓库几乎只能 ETL如果回到二十年前去看数据仓库领域的主流方法论仍然围绕 ETL 展开。那时数据量级远小于今天业务系统以关系型数据库为主报表需求相对固定ETL 工具正好能满足“定时、批量、稳定输出”的要求。当时的数仓建设讲究“模型先行”也就是先定义维度表、事实表再反过来设计抽取逻辑。这种做法的好处是数据一致性高、口径统一坏处是变更成本极高。一个字段语义调整可能要改十几张底层表还要重新回刷几个月甚至几年的历史数据。在那个阶段不是没人想先把原始数据加载到数仓再做转换而是受限于存储和计算成本。很多企业的ODS操作数据存储层已经有这个倾向但通常只保留很短时间而且仍然会做裁剪和清洗。真正意义上的“保留原始数据在仓内转换”并没有成为通用实践。2.2 云数仓让“先加载后转换”变得可行改变发生在大规模并行处理数据库和云基础设施结合之后。Snowflake、BigQuery、Redshift 这类云数仓把存储放到廉价对象存储上计算资源和存储资源可以独立扩展。查询到数据的时候再拉起计算集群用完即可释放这意味着你可以把更多原始数据放在数仓里而不必担心长期占用昂贵的数据库磁盘。云数仓还改变了数仓的定位它不再只是存放报表数据的“成品库”而更像一个可扩展的数据工作区。数据加载进来之后可以用 SQL 随时做探索、清洗、建模、回刷。这种能力上的变化让 ELT 不再是“把转换从中间挪到后面”这么简单而是让整个数据流程从“一次性加工”变成了“可反复迭代的数据资产”。2.3 工具链成熟同步、调度、转换分层理念可行之后工具链也开始分层成熟。数据同步层出现了大量优秀选择比如开源产品、托管服务以及国内云厂商自带的数据集成套件用户只需要配置数据源和目标表就能完成增量或全量加载。转换层则出现了类似 dbt 这样的工具把 SQL 模型变成可测试、可版本控制、可依赖管理的工程代码。在 ELT 被系统讨论之前不少团队是靠手工脚本完成的写一段 Python 把数据从业务库读出来再写一段 Python 做清洗和合并最后用 crontab 调度。这种方案在小团队里还能跑但一旦表数量增加到几十张、几百张依赖关系、重跑机制、错误通知都很难维护。工具链成熟之后ELT 变成了一个可以被标准化、被审查、被重放的工程流程。同步层解决“数据有没有进来”建模层解决“这些数据怎么变成可用的表”测试层解决“变更之后有没有破坏口径”。这一整套体系才是今天大家谈 ELT 时真正在谈的东西。2.4 今天的 ELT 不等于不做建模有一个常见误解ELT 就是不建模把所有数据都堆到数仓里等要用的时候再写临时 SQL。真实工程中这样做是会出事的。数据一旦变多、业务口径一旦变复杂完全没有模型的数仓会退化成“数据沼泽”。今天的 ELT 实践通常仍然会在仓内做分层建模。常见做法是staging 层直接对应源系统原始表只做简单类型矫正保留完整历史。中间层做业务过程拆分、维度统一、指标标准化。应用层面向报表、BI、算法特征等最终消费场景生成宽表、聚合表。关键区别在于这几层都可以更频繁地迭代而且底层原始数据始终保留。哪怕中间层模型建错了也可以基于 staging 层重新组装不需要重新从源系统拉取。这比传统 ETL 的容错能力要强很多。3. 落地一套 ELT 流程先按这个最小路径跑通3.1 先确定架构从哪里加载到哪里无论团队规模多大落地 ELT 的第一步不是选工具而是确定三个问题源数据在哪里、目标存储选什么、转换由谁执行。如果只是小团队试水建议先用一个云数仓加一个同步工具甚至可以用云数据库自己的导入功能。先把一条链路跑通再谈平台化。架构上尽量避免一开始就上很多组件否则很容易在环境配置上耗费大量时间而不是在业务理解上投入精力。一个比较通用的参考架构是数据源业务数据库、应用日志、第三方 API、文件存储。加载层通过 CDC、定时导出或 API 拉取把数据写入数仓的 staging 区。转换层在数仓内用 SQL 或 dbt 构建分层模型。消费层BI 报表、数据服务 API、算法训练集。这个结构看起来简单但它能覆盖大部分分析场景。等到数据量和任务复杂度上去了再逐步增加消息队列、编排引擎、数据质量平台。3.2 抽取与加载先解决“有没有”最小可行的 ELT 起步方式是建一张原始表把源数据原样导入保留所有字段并加上统一的加载时间标记。这个阶段先不做清洗因为 ELT 的核心价值之一就是保留原始数据。以订单数据为例加载表的常见写法是create table raw_orders ( _loaded_at timestamp default current_timestamp, order_id varchar, customer_id varchar, order_date timestamp, status varchar, total_amount numeric, -- 保留源系统所有字段即使暂时用不到 _source_file varchar, _source_ts timestamp );这里要特别注意加载阶段不要只挑选“认为有用的”字段。如果后续发现漏了一个源系统字段还得重新回到数据源补数代价非常高。更好的做法是把所有字段原样保留等建模时再裁剪。这个阶段唯一的重点是让每次加载都可以被识别、被区分、被回滚。不要用覆盖写入尽量使用追加或分区写入。3.3 转换层设计用 SQL 视图或物化表转换层是 ELT 中最需要设计的地方。可以先从视图开始因为视图不占额外存储适合做探索等逻辑稳定后再物化成表提升查询性能。使用 dbt 时一个模型通常就是一个 SQL 文件。例如-- models/staging/stg_orders.sql select order_id, customer_id, order_date, case when status in (paid, completed) then paid else other end as order_status, total_amount from {{ ref(raw_orders) }} where order_date is not null这里的ref(raw_orders)表示依赖 staging 层的原始订单表。dbt 会根据这些引用关系自动构建依赖树运行转换时先跑上游再跑下游避免手动调度顺序出错。如果不使用 dbt也可以直接手工创建视图create view stg_orders as select order_id, customer_id, order_date, ... from raw_orders where order_date is not null;关键是“转换逻辑要有版本、有依赖、有可重复执行性”而不是为了用某个工具而引入它。3.4 增量加载与调度ELT 落地中多数问题出在增量同步。常见的增量方式有三种基于时间戳源表有updated_at字段时同步最近变更的数据。基于 CDC通过日志捕获插入、更新、删除适合数据库表。基于全量对比每次拉取全量到临时表再用 SQL 做 diff适合小表。先判断表的大小和更新频率再决定用哪种方式。很多团队一上来就对所有表做每 5 分钟同步结果源系统压力大目标端重复数据也多。更稳妥的做法是大表用小时间窗或事件触发增量小表用低频率全量。调度上不要把同步和转换塞进同一个任务里跑。建议分成三步先同步再转换最后测试。每一步都打日志并记录运行结果。只有前置步骤成功后续步骤才允许执行。3.5 质量检查与回滚ELT 的好处是原始数据还在但如果不做质量检查下游每天还会被“坏数”影响。一个简单有效的方法是每次加载完成后对关键表做行数变化统计。比如select count(*) as row_count from raw_orders where _loaded_at current_date - interval 1 day;如果行数出现断崖式下跌或激增就要先停下来检查源端而不是继续往下游建模。更完整的做法是在转换层加测试主键唯一性校验金额字段非负校验必要字段非空校验最近批次的记录数不能明显偏离 7 日均值当批次数据异常时要允许任务失败并保留原表数据而不是覆盖已有结果。简单说转换任务最好做成幂等的同一份输入反复执行结果是稳定一致的。遇到上游数据修正时也能直接重跑整个链路。注意不要一上来就把批量数和并发数拉满先用一条样例确认输入、输出和日志都正常。4. 最容易踩坑的不是语法而是这几条边界4.1 源系统压力与加载频率ELT 鼓励你把原始数据加载到数仓但它不鼓励你无节制地把所有源表频率都调高。数据同步任务本质上是在读取源系统数据库会有连接数、IO、锁等成本。如果为了追求“近实时”而对核心交易库每 5 分钟发起一次全量查询影响面可能会很大。更合理的做法是评估每个表的业务重要性和变更频率。用户资料表可能每天变更量不大低频同步就够订单状态表如果业务依赖强可以缩小同步间隔日志类数据走消息队列或对象存储流式导入效果会更好。4.2 增量更新的幂等性与时间窗口增量同步最容易出现的两个问题是重复和漏数。重复通常因为重跑任务数据被再次插入漏数通常因为源系统更新时间晚于同步水位线或者时区处理不一致。建议在水位线设计上留出一定的“边界重叠”。比如用updated_at last_sync_time - interval 10 minutes的方式拉取虽然可能拉回少量重复数据但至少不会漏掉边界上的记录。然后在转换层通过去重逻辑处理重复比让数据缺失更难解决。另外如果任务可以重跑就要使用可重复的写入策略。要么先删除目标表中当前时间分区的数据再写入要么使用基于主键的 merge 逻辑。千万不要在同一个分区里无脑追加否则重跑几次后数据量会翻倍。4.3 转换依赖顺序和重复执行ELT 里任务依赖关系通常由 DAG 管理但 DAG 不会自动帮你发现“数据质量问题”。即使依赖顺序正确上游加载了脏数据下游转换也会把问题放大。因此依赖关系之外还要在关键节点增加行数校验和字段校验。另一个容易踩的坑是“部分重跑”。当某个模型逻辑改完只重跑它本身是不够的因为它下游的表、报表、指标已经基于旧数据生成。推荐做法是沿着血缘关系从变更点开始把下游所有依赖任务重新执行一遍。这在 ELT 工具里通常很简单但需要团队在流程上形成习惯。4.4 权限、敏感数据和成本ELT 会把大量原始数据集中在数仓或数据湖中这意味着数据安全边界发生了变化。过去 ETL 过程中清洗阶段可以提前过滤敏感字段而 ELT 模式下原始数据会原样进入数仓权限控制必须提前跟上。首先确定数据分级哪些字段属于敏感信息需要脱敏、加密或行级权限控制。其次把访问权限控制在 minimal 范围分析师看到的通常是应用层或脱敏层而不是全量原始表。最后记录访问日志至少能在异常操作发生后追踪到具体账号和时间。成本也要提前关注。ELT 里最容易产生成本的是对超大表的重复全量扫描。可以通过分区裁剪、物化视图、按需计算等方式降低查询费用。不要因为“数据在仓内”就觉得可以随意全表扫描计算成本同样会失控。4.5 长表、宽表与历史变更建模选择会影响后续迭代速度。很多分析师习惯一上来建大宽表把订单、用户、商品、支付全部 join 到一起。宽表查询方便但结构一旦定下来任何字段的语义变化都要改表和回刷数据。在 ELT 模式下建议先做较窄的 staging 层和中间层每个业务过程独立建模再按实际需求组装宽表。这样当某个维度变化时影响的只是局部模型而不是整张大宽表。简单说宽表应是消费层的做法不应该成为唯一的建模方式。5. 我的排查顺序从现象到根因5.1 先判断是哪一层失败ELT 链路大致分成同步层、加载层、转换层。出现问题后不要直接改 SQL先判断报错或数据异常发生在哪一层。同步层失败通常表现为任务长时间卡住、延迟升高、源端连接失败。加载层失败表现为数据没有写入目标表或写入行数与源端不一致。转换层失败表现为模型执行报错、查询超时或计算结果和预期不符。先定位是哪一层再往下看细节。这是最省时间的排查顺序。5.2 按输入、环境、权限、资源、参数逐层检查定位到具体层之后我一般按下面的顺序排查看输入。源表结构是否变化新字段是否导致类型不匹配源系统数据是否包含大量空值或异常值看环境。网络是否可达目标库的 schema 是否存在同步工具和数仓驱动的版本是否兼容看权限。执行任务的账号是否有目标表的写权限是否有源表的读权限是否因为数据脱敏策略限制导致查询被拦截看资源。任务运行时数量是否超过数据库并发上限目标表所在分区是否锁表临时磁盘或存储空间是否足够看参数。增量水位线是否正确批次大小是否过高超时时间是否太短时区设置是否一致大多数 ELT 问题都不是复杂逻辑而是在这几项基本配置中出了偏差。先做排除法而不是一上来就翻看 SQL 复杂度。5.3 常见错误示例举几个很常见的例子字段类型不匹配源系统是字符串的数字目标数仓字段是 numeric加载时导入失败。解决思路是先使用 varchar 加载再在转换层做 cast。分区更新异常同步任务写入目标表时没有指定分区导致数据全部落到默认分区下游查询看不到新数据。解决思路是检查写入任务的分区表达式。时区不一致源系统使用 UTC分析师在本地时区看报表结果日期偏移。需要在加载层就用明确时区转换或保留原始时间戳同时加一个本地时间字段。dbt run 报 schema not found模型所在的 schema 没创建或账号不具备建表权限。解决思路是检查数据库连接配置和权限。同步任务卡住但不报错大概率是源端锁或无主键表全量扫描太慢。解决思路是考虑使用 CDC 或限制扫描范围。这些问题看起来很小但会反复出现。把它们提前写成团队排查文档比每次都临时查资料更高效。5.4 如何确认结果正确确认结果正确不能只看“任务跑成功了”。我通常用四个检查数据量是否在合理范围。主键重复率是否为 0 或接近 0。关键指标订单金额、用户数、转化率是否与源系统或原始数据吻合。随机抽样几条数据手工核对字段级逻辑是否正确。如果四个检查都通过才认为这条 ELT 链路的输出可信。不要因为调度界面显示绿色就对结果完全放心数据质量是另一套标准。6. ELT 适合谁不适合谁6.1 适合场景ELT 特别适合这几类团队第一分析需求变化快的团队。今天刚确定的指标明天可能因为业务方向调整而重改。ELT 可以快速重新建模不必回到源系统重新拉数。第二希望把数据资产摆在自己手里的团队。原始数据进入数仓后不再受制于某个外部管道开发者数据团队可以随时查询和复现。第三需要探索式分析的团队。分析师和算法工程师希望直接访问原始数据做用户行为路径、特征提取、异常检测等非固定报表分析。第四刚刚开始数仓建设、历史包袱小的团队。没有老的 ETL 任务拖着用 ELT 建新的流程会更顺畅。6.2 不适合场景ELT 不是银弹。下面这些场景里它反而会带来问题。第一种是数据质量要求极高且模型非常稳定。比如金融核心报表、监管报送这类场景需要严格的输入校验和审批流程ETL 在进入数仓前完成强制清洗反而是更稳妥的做法。第二种是源系统无法承受全量抽取。比如某些遗留系统读压力已经很大再接入全量加载会导致生产事故。此时要么做增量同步要么在源端只抽取必要字段本质上更接近 ETL。第三种是数据合规要求原始数据不能进入分析环境。有些数据由于隐私和安全原因不允许在分析数仓中长期保留原文必须在管道中完成脱敏或过滤ELT 的“先加载原始数据”就不符合合规要求。第四种是小数据集上的简单场景。总共几张表、几千行数据用 ELT 要建仓库、建同步、建建模层反而过度设计。此时直接查业务库或做一个轻量导出更省事。6.3 二十年后的判断ELT 不会消失但会继续变化从工具视角看ELT 经过了脚本、可视化同步工具、云数仓原生能力、转换层工具等多个阶段。接下来它会朝着“加载后自动建模、自动治理、自动指标管理”的方向演化。当前端的自动建表、自动血缘、指标中台越来越完善ELT 中的“T”会变得更智能化但核心思想不会变先把数据保留下来再通过一次次迭代去理解它、加工它。对正在选型的人来说也许不需要过度纠结某个工具是不是“纯 ELT”。你真正要做出判断的是团队能否接受“数据先存在再被逐步理解”的工作方式。如果接受ELT 会帮你省掉大量前期建模沟通成本如果不接受那无论工具怎么宣传落在地上还是 ETL 的变体。这不是一个技术路线之争更像是一次关于“什么时候需要确定性”的管理判断。因此真正值得长期关注的问题不是“ELT 比 ETL 快多少”而是“我们是否愿意让数据在加工之前先具备被探索的余地”。
返回列表