ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

dlt 1.21.2 破坏性变更详解:复合提示(Compound Hints)的优先级与替换规则

dlt 1.21.2 破坏性变更详解:复合提示(Compound Hints)的优先级与替换规则 dlt 1.21.2 破坏性变更详解复合提示Compound Hints的优先级与替换规则【免费下载链接】dltdata load tool (dlt) is an open source Python library that makes data loading easy ️项目地址: https://gitcode.com/GitHub_Trending/dl/dlt在 dlt 中primary_key、merge_key、cluster、partition这几类“作用于多列的列级属性”被统一称为复合提示compound hints它们直接决定增量加载去重、merge 写入以及目标端分区/聚簇等关键行为。自 v1.21.2 起对应 PR #3431dlt 为复合提示引入了显式优先级与替换规则直接传入的primary_key/merge_key覆盖列级定义重新定义提示时不再累加而是整体替换。阅读本文可以帮你理解这三条破坏性变更的具体语义、掌握在资源与apply_hints两种场景下的正确写法并结合源码确认底层“替换”是如何实现的从而安全地从旧版本迁移。一、变更背景为什么 v1.21.2 要改复合提示的解析方式在 v1.21.2 之前所有复合提示都是以累加additive方式合并的同一列上的旧提示与新提示会被同时保留。这种“只加不减”的行为在跨运行run-to-run修改键定义时会带来意外结果——例如把partition从col_1挪到col_2后两列会同时被标记为分区列与用户直觉相悖。v1.21.2 将解析规则调整为三条明确的语义分别针对“同一定义内多层级冲突”与“跨运行重新定义”两类场景。理解这组规则的前提是区分提示的两个传入层级直接资源级提示primary_keycol_1、merge_key(a,b)直接作用在表上列级提示columns{col_2: {primary_key: True}}把属性写死在某一列上。复合提示目前支持的四种属性为primary_key、merge_key、cluster、partition详见 Schema 文档 Compound hints 小节。二、变更一直接primary_key/merge_key优先于列级提示当你在同一资源定义里同时给出直接键提示和列级键提示时直接提示获胜列级提示被忽略。import dlt pipeline dlt.pipeline( pipeline_namemy_pipeline, destinationduckdb, dataset_namemy_data, ) dlt.resource( namemy_table, primary_keycol_1, # 直接提示 columns{col_2: {primary_key: True}}, # 列级提示 ) def my_resource(): yield {col_1: 1, col_2: 2} pipeline.run(my_resource) # 结果只有 col_1 是主键col_2 的列级 primary_key 被忽略这一优先级规则同样适用于merge_key以及通过apply_hints同时传入直接键与列级键的情形my_resource.apply_hints( merge_keycol_1, columns{col_2: {merge_key: True}}, ) # 结果只有 col_1 是 merge key源码印证表级提示覆盖列级设置该优先级在解析阶段由DltResourceHints._merge_keys实现。它按primary_key、merge_key的顺序把表级键提示下放到列并在下放前先清除列上已存在的同名复合属性staticmethod def _merge_keys(dict_: TResourceHints) - None: Applies primary_key and merge_key hints to columns. Table-level hints override column-level settings. if primary_key in dict_: DltResourceHints._merge_key(primary_key, dict_.pop(primary_key), dict_) if merge_key in dict_: DltResourceHints._merge_key(merge_key, dict_.pop(merge_key), dict_)见 hints.py。其内部调用_merge_key后者第一步就执行remove_compound_props(partial[columns], {hint})把该属性从所有列上移除再按表级指定的键重新打上标记——这正是“直接提示优先”的落地机制见 hints.py。三、变更二重新定义复合提示会整体替换旧配置这是对增量管道影响最大的一条。若某个资源已经提取过schema 已落盘再次以新的复合提示定义它时新的属性会完全替换旧配置而不是与之合并。import dlt pipeline dlt.pipeline( pipeline_namemy_pipeline1, destinationduckdb, dataset_namemy_data, ) # 第一次partition 在 col_2 dlt.resource(namemy_table, columns{col_2: {partition: True}}) def my_resource(): yield {col_1: 1, col_2: 2} pipeline.run(my_resource) # 第二次改为 partition 在 col_1 dlt.resource(namemy_table, columns{col_1: {partition: True}}) # type: ignore[no-redef] def my_resource(): yield {col_1: 1, col_2: 2} pipeline.run(my_resource) # 只有 col_1 保留 partitioncol_2 失去了该属性 assert ( pipeline.default_schema.tables[my_table][columns][col_1].get(partition) is True ) assert not pipeline.default_schema.tables[my_table][columns][col_2].get(partition)源码印证merge_compound_propsFalse的替换路径“替换而非合并”的核心在 schema 合并工具中通过merge_compound_props开关控制。当该开关为False时merge_columns会先调用_collect_and_remove_compound_props把目标列上出现的复合属性全部清掉再以新值为准写入def merge_columns( columns_a, columns_b, merge_compound_props: bool True, ) - TTableSchemaColumns: if not merge_compound_props: _collect_and_remove_compound_props(columns_b, columns_a) # ... 逐列合并columns_b 的非默认值覆盖 columns_a见 utils.py 与 utils.py。在提取器把资源新提示合并进已存储 schema 时dlt 正是传入了merge_compound_propsFalse让新定义具有权威authoritative地位auth_schema, normalize_identifiersTrue, merge_compound_propsFalse见 extractors.py 与 extractors.py。merge_table的文档字符串也明确说明了两种取值语义True时复合属性“以累加方式合并”False时“partial_table中存在的复合属性为权威table中存在但partial_table中缺失的复合属性会被移除”见 utils.py。注意事项来自 schema.md 的警告直接primary_key/merge_key会默认给对应列设置nullableFalse除非显式指定nullableTrue。当你之后重新定义键提示时原先属于键的列会保留其既有可空性而不会自动被重置回nullableTrue。此外把已提取资源的primary_key/merge_key重新定义为空值并不会清空 schema 中已有的键属性——旧键会原样保留。四、变更三通过apply_hints传入的直接键提示是权威的当调用apply_hints时直接键提示与列级提示遵循不同的合并策略直接键提示如primary_keycol_1——替换现有键配置不合并列级复合提示如columns{col_1: {primary_key: True}}——合并进现有 schema。# 直接键替换旧键 my_resource.apply_hints(primary_keycol_1) # 替换之前在 col_2 上的主键 # 列级与新列键合并共存 my_resource.apply_hints(columns{col_1: {primary_key: True}}) # 若 col_2 已是主键则 col_1 与 col_2 同时成为主键源码印证apply_hints中键与列的不同分支在DltResourceHints.apply_hints里直接键与列级提示走的是完全不同的代码分支恰好对应“替换”与“合并”两种语义if columns is not None: # ... t[columns] merge_columns(t[columns], columns) # 列级合并 ... if primary_key is not None: t[primary_key] primary_key # 直接键整体覆盖 if merge_key is not None: t[merge_key] merge_key # 直接键整体覆盖见 hints.py。columns分支调用merge_columns做累加合并而primary_key/merge_key分支则是对提示模板的直接赋值覆盖随后在 schema 落盘时由第二节的替换路径执行“先清后写”。五、迁移建议与适用边界从旧版本升级时若你的管道依赖“复合提示只加不减”的旧行为例如跨运行不断叠加分区列需改为显式声明期望的完整键集合因为新版本会按最后定义整体替换。同一定义内避免冲突不要同时写primary_keycol_1与columns{col_2: {primary_key: True}}直接提示会静默覆盖列级提示。apply_hints分层使用需要“增量加列/加属性”时用列级columns需要“重新指定表主键/merge 键”时用直接键提示。适用前提以上语义与优先级规则适用于 v1.21.2 及以后版本仓库内 schema.md 中的示例均基于 DuckDB 目标端验证可复现断言结果。若你仍在使用 v1.21.2 之前的版本旧行为下复合提示以累加方式合并迁移前请先核对已落盘的 schema 键属性。相关变更在后续版本说明中亦有提及见 release-notes/1.22.md。【免费下载链接】dltdata load tool (dlt) is an open source Python library that makes data loading easy ️项目地址: https://gitcode.com/GitHub_Trending/dl/dlt创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进