数据仓库 ETL 缓慢 - 更改维度中的主键?
Posted
技术标签:
【中文标题】数据仓库 ETL 缓慢 - 更改维度中的主键?【英文标题】:Data Warehouse ETL slow - change primary key in dimension? 【发布时间】:2012-07-02 01:02:45 【问题描述】:我有一个按星型模式组织的有效 mysql 数据仓库,我正在使用 Talend Open Studio for Data Integration 5.1 创建 ETL 流程。我希望这个过程每天运行一次。我估计其中一个维度表 (dimUser) 将有大约 200 万条记录和 23 列。
我在 Talend 中创建了一个可以运行的小型测试 ETL 流程,但考虑到每天可能需要更新的数据量,当前的性能不会降低它。 ETL 过程需要四分钟来更新或插入 1,000 条记录到 dimUser。如果我假设记录数与 UPDATE 或 INSERT 时间量之间存在线性关系,那么 ETL 不可能在 3-4 小时内完成(我的希望),更不用说一天了。
由于我不熟悉 Java,我将 ETL 编写为 Python 脚本并遇到了同样的问题。虽然,我确实发现如果我只做 INSERT,这个过程会快得多。我很确定瓶颈是由 UPDATE 语句引起的。
dimUser 中的主键是一个自增整数。我的朋友建议我废弃这个主键并用一个多字段主键(在我的例子中是 2-3 个字段)替换它。
在我将测试数据从仓库中取出并更改架构之前,任何人都可以提供与
相关的建议或指南-
数据仓库的设计
ETL 过程
让 ETL 流程每天插入或更新几百万条记录是多么现实
我朋友的建议会有很大帮助吗
如果您需要任何进一步的信息,请告诉我,我会发布。
更新 - 附加信息:
mysql> describe dimUser;
Field Type Null Key Default Extra
user_key int(10) unsigned NO PRI NULL auto_increment
id_A int(10) unsigned NO NULL
id_B int(10) unsigned NO NULL
field_4 tinyint(4) unsigned NO 0
field_5 varchar(50) YES NULL
city varchar(50) YES NULL
state varchar(2) YES NULL
country varchar(50) YES NULL
zip_code varchar(10) NO 99999
field_10 tinyint(1) NO 0
field_11 tinyint(1) NO 0
field_12 tinyint(1) NO 0
field_13 tinyint(1) NO 1
field_14 tinyint(1) NO 0
field_15 tinyint(1) NO 0
field_16 tinyint(1) NO 0
field_17 tinyint(1) NO 1
field_18 tinyint(1) NO 0
field_19 tinyint(1) NO 0
field_20 tinyint(1) NO 0
create_date datetime NO 2012-01-01 00:00:00
last_update datetime NO 2012-01-01 00:00:00
run_id int(10) unsigned NO 999
我使用代理键是因为我读过它是一种很好的做法。因为,从业务的角度来看,我想了解潜在的欺诈活动(比如 200 天用户与状态 X 相关联,然后第二天他们与状态 Y 相关联 - 他们可能已经移动或他们的帐户可能已经妥协),这就是保留地理数据的原因。字段 id_B 可能有几个不同的 id_A 值与之关联,但我有兴趣了解不同的 (id_A, id_B) 元组。在此信息的上下文中,我的朋友建议将 (id_A, id_B, zip_code) 之类的内容作为主键。
对于大多数日常 ETL 流程 (>80%),我只希望为现有记录更新以下字段:field_10 - field_14、last_update 和 run_id(此字段是我的 etlLog 表的外键和用于 ETL 审计)。
【问题讨论】:
如果你把你的主键改成在更新过程中可能会改变的东西,那么每次更新时都需要重新计算索引,这样会比较慢。在一个中等大小的表上只更新 100 行需要 4 分钟,这似乎很奇怪,也许是您的脚本而不是架构有问题。您是否尝试过直接在 sql 和脚本中对更新进行基准测试? 你是怎么想出每天几百万的? 你的key没问题,你加载的时候使用key pipeline吗?您在 dimUSer 上的业务密钥是什么? @Damir:200 万的价值来自历史观察数据。什么是关键管道? 请阅读 KImball 的书。这都是普通的香草。 【参考方案1】:这是我对您的问题的看法。
1) 仓库设计:
阅读 Ralph Kimball 的书:数据仓库工具包。
您的维度表有一堆名称无意义的列。应该为该列指定一个具有业务意义的名称,而不是 field_5。数据仓库是为了便于业务和报告人员查询。
我在这里看不到任何事实表。了解用户维度的用途在其设计中很重要。
2) ETL 过程
您是否确定了 ETL 流程中的瓶颈在哪里?是从源读取数据、转换数据还是写入数据库?您可能以 40,000 行/秒的速度写入,但如果您只能从 XML 数据源读取 1,000 行/秒,那么您不会走得太远。
您是否考虑过先将更改的记录加载到数据库中的阶段表中,不进行任何转换,然后使用 SQL 来转换和更新数据?通常,您会发现数据库中的性能比将工作卸载到 ETL 工具要好。
3) 如果硬件可以处理的话,每天更新几百万条记录是非常现实的。我认为重要的是要了解您是否只是要覆盖更改的类型 1 维度(在这种情况下,删除更改行,然后插入,可能比更新/其他/插入更好的选择)。
如果您要在类型 2 维度中保留更改历史记录,您可能需要考虑在单独的小维度中对要跟踪更改的字段进行雪花化处理。当您拥有非常大的“客户”维度时,Kimball 会讨论此技术。然后,您将使用一个定期快照事实表,它允许您跟踪用户随时间的变化。
4) 您朋友提出的从自然业务键中创建主键的建议对于数据仓库环境来说不是一个好主意。我们创建了一个整数代理键,以便我们可以将它包含在事实表中,以保持它们的精简,因为它们将比维度表大几个数量级。
【讨论】:
@N West:感谢您的回答,尽管我认为您从我的帖子中获取的信息有点过于字面意思了。上面列出的某些字段具有通用名称,因为我在商业环境中工作,并且不希望发布可能识别我为哪个雇主工作的信息。此外,虽然我确实征求了与数据仓库设计相关的答案,但我从未想过我会收到有关字段命名实践的回复。另外(再次),我确实有事实表,但认为没有必要发布数据仓库的整个架构。 @Jubbles - 明白了:) - 我经常看到来自 Oracle ERP 之类的“AttributeX”列在数据仓库中重复,而不是给它们提供可靠的业务名称。至于模式 - 维度的设计方式通常会受到其在事实中的使用方式的影响。如果您要进行详细的用户分析,将用户维度拆分为多个维度以允许对事实表进行更快的切片/切块可能是有意义的。以上是关于数据仓库 ETL 缓慢 - 更改维度中的主键?的主要内容,如果未能解决你的问题,请参考以下文章