Materialized Lake Views in Microsoft Fabric: When Your Medallion Fits in a SELECT Statement
TL;DR · AI 摘要
微软 Fabric 的 Materialized Lake Views(MLV)通过 SQL 语句实现数据流水线自动化,简化了传统多层架构的复杂性。
核心要点
- Materialized Lake Views(MLV)通过 SELECT 语句实现数据流水线自动化。
- MLV 将传统五层架构简化为一个声明式 SQL 层。
- MLV 自动处理刷新、依赖跟踪和数据质量检查。
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- Materialized Lake Views in Microsoft Fabric
- 定义与特性
- 基于 SELECT 语句定义
- 自动刷新与依赖管理
- 存储为 Delta 表
- 生命周期
- 创建
- 刷新
- 监控
- 删除
- 优势
- 简化数据流水线
- 减少调试复杂性
- 自动数据质量检查
金句 / Highlights
值得收藏与分享的关键句。
Materialized Lake Views (MLVs) go generally available in March 2026, offering a new way to define data pipelines with SQL.
An MLV is nothing else but a SELECT statement that learned to materialize itself, manage its own dependencies, schedule its own refresh, and check its own data quality.
Before MLVs, building a single bronze-to-silver-to-gold flow looked roughly like this: you’d write a notebook for each transformation, set up a Data Factory pipeline to call them in the right order, c
Microsoft Fabric 中的 Materialized Lake Views:当你的 Medallion 只需一条 SELECT 语句 | Towards Data Science
数据工程
Microsoft Fabric 中的 Materialized Lake Views:当你的 Medallion 只需一条 SELECT 语句
五个层面融合为一个声明式层级
Nikola Ilic
2026 年 6 月 20 日
15 分钟阅读
分享
长期以来,在 Microsoft Fabric 中构建一个 Medallion 架构意味着要将多个移动部件组合成一个小型交响乐团:使用笔记本进行转换、使用管道进行编排、使用计划进行刷新、使用自定义代码进行数据质量检查,以及使用 Monitor Hub 来监控是否真的有东西正常运行。每一层都工作得很好,直到某一层出了问题,然后你必须弄清楚是哪一层出了问题,原因是什么,以及哪些下游层受到了影响。
如果你曾经尝试调试一个银层,因为它没有更新,而青铜层的笔记本在三小时前失败了,那么你完全知道我在说什么。
然后,在 2026 年 3 月的 FabCon Atlanta 上,Materialized Lake Views(MLVs)正式发布。它们讲述的故事很简单:如果整个 Medallion 管道只需要几个 SELECT 语句,会怎样?
让我带你一步步了解整个过程——它们是什么,如何工作,预览版和 GA 版之间有哪些变化,以及它们在你的架构中适合(不适合)哪些地方。
Materialized Lake View – 什么是?
Materialized Lake View 是在 Spark SQL 或 PySpark 中定义的持久化、自动刷新的视图。你编写一个 SELECT 查询来描述你想要的转换,Fabric 会负责执行、存储、刷新、依赖跟踪和数据质量保证。
结果以 Delta 表的形式存储在你的湖仓中。因此,下游消费者,如 Power BI Direct Lake、Spark 笔记本、SQL 端点等,可以像查询任何其他 Delta 表一样查询它。不需要特殊处理,也不需要不同的语法。
用通俗的话来说:MLV 就是一条学会了自我实现、管理自身依赖、安排自身刷新并检查自身数据质量的 SELECT 语句。
作者提供的图片
好的,这听起来不错。但它实际上替换了什么?
这是一个合理的问题。在 MLVs 之前,构建一个从青铜到银到金的单一流程大致如下:你会为每个转换编写一个笔记本,设置一个 Data Factory 管道来按正确顺序调用它们,配置计划,构建自定义验证逻辑,然后连接 Monitor Hub 来监控失败情况。五个不同的层面,当某处出问题时,有五个不同的地方需要调试。
有了 MLVs,所有这些都融合到了声明式 SQL 中。你描述你想要什么。Fabric 会处理其余部分。
创建:语法
以下是直接来自 Microsoft Learn 参考的完整 Spark SQL 伪代码语法,用于创建 MLV:
CREATE [OR REPLACE] MATERIALIZED LAKE VIEW [IF NOT EXISTS]
[workspace.lakehouse.schema].MLV_Identifier
[(CONSTRAINT constraint_name CHECK (condition) [ON MISMATCH DROP | FAIL], ...)]
[PARTITIONED BY (col1, col2, ...)]
[COMMENT “description”]
[TBLPROPERTIES (”key1”=”val1”, ...)]
AS select_statement一个实际例子——清理从产品和订单中连接而来的订单数据,包含数据质量约束和分区:
CREATE OR REPLACE MATERIALIZED LAKE VIEW silver.cleaned_order_data
(
CONSTRAINT valid_quantity CHECK (quantity > 0) ON MISMATCH DROP
)
PARTITIONED BY (category)
COMMENT “Cleaned order data joined from products and orders”
AS
SELECT
p.productID, p.productName, p.category,
o.orderDate, o.quantity, o.totalAmount
FROM bronze.products p
INNER JOIN bronze.orders o ON p.productID = o.productID有两个值得注意的地方。首先,MLV 名称是不区分大小写的(MyView 变成 myview)。其次,所有大写名称的模式(如 MYSCHEMA)不被支持,因此请使用混合大小写或小写。
你还需要一个启用模式的 lakehouse 和 Fabric Runtime 1.3 或更高版本。如果你的 lakehouse 没有启用模式,MLV 将不可用,这是首要的先决条件。
刷新:MLV 的核心
这就是 MLV 停止聪明,开始变得智能的地方。
当源数据发生变化时,Fabric 的最佳刷新引擎会查看血缘中的每个 MLV,并提出一系列问题:实际上有什么变化了吗?我可以只处理这些变化吗?还是需要从头开始重新构建?
三种可能的结果:
- 跳过刷新 – 源数据没有变化。不要浪费计算资源。继续处理下一个。
- 增量刷新 – 仅处理新或更改的行。快速、经济、理想。
- 全量刷新 – 从头重新构建整个内容。最慢的路径,当增量刷新不安全或不可行时使用。
但,这一点很重要,增量刷新并不是免费的。它有一些先决条件:
- MLV 引用的每个源表必须启用 Delta 变更数据源(CDF)(delta.enableChangeDataFeed=true)。
- 源必须是 Delta 表。非 Delta 源总是会进行全量刷新。
- 数据必须是只追加的。如果你的源有更新或删除,Fabric 会回退到全量刷新。
- 查询必须仅使用受支持的 SQL 构造(稍后会更详细地介绍这一点)。
如果没有启用 CDF,最佳刷新只能在跳过和全量之间选择。启用 CDF 后,增量刷新的完整路径就打开了。在只追加的工作负载中,启用 CDF 对存储或性能没有可衡量的影响,因此几乎没有理由不启用它:
ALTER TABLE bronze.orders SET TBLPROPERTIES (delta.enableChangeDataFeed = true);
ALTER TABLE bronze.products SET TBLPROPERTIES (delta.enableChangeDataFeed = true);它还能变得更好吗?实际上,是的!这正是 GA 故事真正开始的地方。
一般可用阶段有哪些新功能?
MLV 在 Build 2025 预览版中首次推出。从那时到 2026 年 3 月的 GA,微软填补了最重要的空白。五个重大变化使 MLV 从“有趣”变成了“生产就绪”:
- 多计划支持
- 更广泛的增量刷新覆盖范围
- PySpark 编写(预览)
- 使用 Replace 进行原地更新
- 更强的数据质量控制
让我逐一介绍它们。
1. 多计划支持
在预览版本中,你只能在单个计划中刷新湖仓中所有的 MLV。财务部门需要每小时更新,而分析部门只需要每六小时更新一次?你只能通过笔记本来绕过这个问题,但这会破坏依赖感知、错误报告和重试逻辑。由笔记本触发的刷新无法显示 MLV 的错误详情。错误只会在单元格输出中显示,而依赖视图对此一无所知。错误可能会持续数周,而没有人知道数据管道已经损坏。
现在,你可以在单个湖仓中定义多个命名计划,每个计划针对视图的一个特定子集。财务管道每小时刷新一次。分析每六小时刷新一次。营销每15分钟刷新一次。所有这些都在同一个湖仓中完成,无需编写自定义代码。
当一个命名计划运行时,Fabric 仍然会按照正确的顺序刷新所有上游依赖项,同时并行运行独立视图,并在中央集中显示错误。如果一个运行已经在进行中,而计划又触发了,新的运行将被跳过,下一个窗口将按预期继续进行,因此你无需担心运行之间相互覆盖的问题。
2. 更广泛的增量刷新
以前,增量刷新经常会退化为全量刷新,因为“支持”的 SQL 构造列表非常有限。在 GA 版本中,这个列表显著扩展了。当定义中包含以下内容时,MLV 现在可以进行增量刷新:
- 带有 GROUP BY 的聚合函数,如 COUNT 和 SUM
- 左外连接和左半连接
- 公共表表达式(CTEs)
这是一个重要的变化。我参与过的大多数实际奖章管道都使用了这些模式,现在它们可以符合增量处理的条件,而无需重写。通过最佳刷新功能,内置的决策引擎会检查每次刷新,评估更改数据的体积与全量重新计算的成本,自动选择更快的路径。
我听到你说,我听到了:Nikola,如果我的查询使用了引擎无法增量处理的内容,会怎样?不用担心,这比听起来容易得多 🙂 使用不支持的构造并不会阻止你创建 MLV。它只是意味着 Fabric 会使用全量刷新而不是增量刷新。最佳刷新在需要时会自动退回到全量刷新,因此你通常不需要强制使用全量刷新。如果你想强制使用全量刷新(例如,在更正后重新处理数据),可以使用以下一行代码:
REFRESH MATERIALIZED LAKE VIEW silver.cleaned_order_data FULL;3. PySpark 编写(预览)
这一点非常重要!SQL 在你的转换逻辑涉及自定义 Python 库、机器学习推理调用或封装复杂业务规则的 UDF 时表现非常出色。但一旦遇到这些情况,你就会遇到 MLV 仅限于 SQL 的限制。
通过 PySpark 编写,你现在可以使用 PySpark 和熟悉的 DataFrameWriter API,从 Fabric 笔记本创建、刷新和替换 MLV。fmlv 模块提供了一种基于装饰器的模式,详情请参阅官方 PySpark MLV 参考文档:
import fmlv
from pyspark.sql import functions as F
@fmlv.materialized_lake_view(
name=”LH1.silver.customer_silver”,
comment=”Cleaned & enriched customer silver MLV”,
partition_cols=[”year”, “city”],
table_properties={”delta.enableChangeDataFeed”: “true”},
replace=True
)
@fmlv.check(name=”non_null_sales”, condition=”sales IS NOT NULL”, action=”DROP”)
def customer_silver():
df = spark.read.table(”bronze.customer_bronze”)
cleaned_df = df.filter(F.col(”sales”).isNotNull())
enriched_df = cleaned_df.withColumn(”sales_in_usd”, F.col(”sales”) * 1.0)返回 enriched_df
一些值得了解的 PySpark 潜在问题:
- 在撰写本文时,PySpark MLV 仍处于预览阶段。
- 目前,由 PySpark 编写的 MLV 始终执行完整刷新。PySpark 的最佳刷新方式已在路线图中,但尚未实现。
- @fmlv 装饰器不支持动态参数或变量。所有参数必须硬编码。
- 不能从 PySpark 临时视图(createOrReplaceTempView)创建 MLV – 引擎无法看到会话作用域的视图。请使用物理 Delta 表或其他 MLV 作为数据源。
- 不要删除定义 MLV 的笔记本。没有它,计划刷新将失败。
因此,如果你的转换可以清晰地用 SQL 表达,那么从性能角度来看,SQL 仍然是更好的选择。PySpark MLV 解锁了仅靠 SQL 无法实现的场景。
### 4. 原地更新(Replace)
业务逻辑发生变化。一个筛选条件发生偏移。一个连接增加了一列。一个聚合添加了一个指标。在预览阶段,更新 MLV 定义需要删除并重新创建,这会丢失刷新历史并迫使下游消费者重新连接。
现在,通过 Replace 功能,你可以原地更新 MLV 的定义。Fabric 会验证新的逻辑,将其替换进去,并保留视图的身份、元数据和血缘关系。下游依赖关系保持不变。适用于 SQL(CREATE OR REPLACE)和 PySpark(replace=True)。
这是那些“低调”的 GA 特性之一,虽然没有头条新闻,但对日常使用非常重要。如果你曾经在生产运行时需要协调删除和重新创建一个被大量使用表,你一定知道其中的痛苦。有了这个功能,这种痛苦将不复存在。
### 5. 更强的数据质量
数据质量约束在 MLV 中并不是什么新东西,但在 GA 阶段,它们得到了重大升级。现在你可以:
- 使用基于表达式的逻辑,结合多个列
- 在单个规则中应用算术和内置函数
- 调用会话作用域的用户自定义函数,用于在 Python 而非 SQL 中实现的验证逻辑
结合自动生成的数据质量报告,你将获得接近内置数据可观测性层的功能。你可以快速发现哪些规则最常失败,影响了哪些视图,以及随时间推移趋势如何变化,而无需构建单独的监控管道。
## 血缘视图 – 免费获取依赖关系
当一个 MLV 引用另一个(或一个表)时,Fabric 会自动推断这种关系。无需手动配置,也无需外部编排工具。这些依赖关系是从你的 SQL 中发现的。
这个依赖关系图会成为你湖仓中的可视化血缘。每个节点代表一个转换。箭头显示执行顺序。Fabric 确保当青铜数据到达时,青铜到白银的 MLV 首先运行,然后白银到黄金的 MLV 会针对刚刚更新的白银数据运行。
这就是声明式方法真正发挥作用的地方。你不是在编写流水线。你不是在定义编排。你只是写出每一层应该是什么样子,Fabric 会自动确定顺序。声明式方法的美妙之处就在于此。
一些有用的行为需要了解:
- 独立视图可以并行运行
- 错误会集中显示,而不是在笔记本单元格输出中丢失
- 当运行进行时,血缘视图会每两分钟自动刷新一次
- 所有快捷方式在血缘视图中都被视为源实体
- 您可以将自定义的 Spark 环境附加到 materialized lake views 的血缘关系中,以在刷新过程中优化性能和资源使用。
## 数据质量 – 已声明!
我上面已经提到过这一点,但它值得单独成节,因为这是使 MLVs 与手工构建的管道有所不同之处之一。
每个 MLV 都可以附加一个或多个数据质量约束:
CREATE OR REPLACE MATERIALIZED LAKE VIEW silver.valid_orders
(
CONSTRAINT positive_quantity CHECK (quantity > 0) ON MISMATCH DROP,
CONSTRAINT valid_date CHECK (orderDate >= ‘2020-01-01’) ON MISMATCH FAIL
)
AS
SELECT * FROM bronze.orders
两种操作类型:
- DROP – 违规的行将被移除,计数会记录在血缘视图中,管道将继续运行
- FAIL – 刷新会在第一个违规处停止。如果您没有指定,这也是默认行为
如果存在多个约束且配置了两种行为,FAIL 优先级更高。
违规情况会出现在血缘视图和运行详情中。很好,但实际中这到底是什么样子呢?在数据质量报告中,您将看到按约束、按视图、随时间变化的计数。因此,如果一个通常删除 0.1% 行的约束突然删除了 15% 的行,您将看到这一峰值,并确切知道是哪条规则失败了,以及它属于哪个视图。这是您原本必须手动构建的质量信号。
微软文档还指出,新的基于表达式的约束支持内置的 Spark/SQL 函数,如 UPPER()、LOWER()、TRIM()、COALESCE()、INITCAP() 和 DATE_FORMAT(),因此您的 CHECK 条件可以不仅仅是简单的比较。
## MLVs 的优势与局限
MLVs 并不是万能的解决方案。微软文档在这一点上非常直接,明确指出了它们适用的场景和不适用的场景。
使用 MLVs 的情况包括:
- 频繁访问的聚合(如每日总计、月度指标),其中预计算的结果比重新运行昂贵的查询更有效
- 需要跨多个大型表进行复杂连接,并且所有消费者都需要一致性的场景
- 您希望以统一、声明性方式应用的数据质量规则
- 从多个来源组合数据并受益于自动刷新的报表数据集
- 鸢尾设计模式 – 从青铜层到白银层再到黄金层,定义为 SQL 转换
不使用 MLVs 的情况包括:
- 查询仅运行一次或很少 – 预计算不会有所帮助
- 转换已经很简单且很快
- 您需要非 SQL 逻辑,如机器学习推断、API 调用或复杂的 Python 处理 – 笔记本仍然更合适(尽管 PySpark MLVs 正在逐步弥合这一差距)
- 您需要流处理的亚秒级延迟 – 这属于实时智能的领域
在这里,我想补充一个个人的见解。我目前正深入参与一个微软 Fabric 项目,其中白银层的设计选择 – 数据仓库与 Lakehouse(使用 MLVs) – 正在桌面上激烈讨论。而我不断回到的一个观点是:MLVs 并不像一些人所描述的那样与数据仓库竞争。它们实际上是在与您原本会在 Lakehouse 中构建的笔记本和管道的混乱结构竞争。如果您团队已经精通 SQL,并且转换自然地存在于 SELECT 语句中,那么在基于 Lakehouse 的架构中将 MLVs 作为白银层的论点确实是强有力的。
## 细节 – 在投入之前需要了解的内容
如果我把 MLVs 描述成万能的解决方案,那对您来说是一种误导。它们确实有一些重要的限制,其中一些会对您的架构产生影响:
- 不支持跨湖仓的血缘关系和执行 – 所有来源、MLV 和依赖项必须位于同一个湖仓中。如果你使用 Fabric 数据仓库表作为数据源,必须首先在你的湖仓中为其创建一个快捷方式。
- 不支持 DML 语句 – 你无法对 MLV 执行 INSERT、UPDATE 或 DELETE 操作。数据仅由 SELECT 语句生成。
- 定义中不支持时间旅行查询 – VERSION AS OF 和 TIMESTAMP AS OF 不被允许。
- SQL 定义中不支持 UDF – 尽管 PySpark 的编写方式通过会话作用域的 UDF 填补了这一空白。
- 不支持临时视图作为数据源 – SELECT 可以引用物理表和其他 MLV,但不能引用临时视图。这也适用于 PySpark:createOrReplaceTempView() 的输出对 MLV 引擎不可见。
- 在计划刷新期间,会话级别的 Spark 属性不适用 – 应该在湖仓或工作区级别进行设置。
- 模式名称的大小写很重要 – 不支持全大写的模式名称。请使用混合大小写或小写。
- 区域可用性 – 截至本文撰写时,MLV 在美国南部中央地区不可用。
对于大多数数据管道来说,以上限制都不是决定性的问题。但在你将架构提交给 MLV 并在中途发现这些限制之前,了解这些信息是很有必要的。
## 总结
如果你一直在 Fabric 中使用笔记本和管道构建勋章设计模式,那么 MLV 值得认真考虑。它们将五个层面合并为一个声明式层。依赖关系管理是自动的。数据质量是内置的。血缘关系是可见的。并且从 FabCon Atlanta 开始,它们已经具备了生产就绪的条件。
微软的路线图非常明确:PySpark 编写的 MLV 的最佳刷新功能即将到来,更多的 SQL 操作符将具备增量刷新资格,并且与 Fabric 其他工作负载的更深入集成也在进行中。这是一个里程碑,而不是终点 – 我很期待看到 MLV 在接下来几个季度的发展,特别是在 PySpark 增量刷新和微软可能讲述的跨湖仓故事方面。
我将记住的两个要点是:
- 如果你的 ELT 中的 “T” 是 SQL,那么它现在写起来、安排执行以及信任起来都变得容易得多。
- MLV 并不会取代每一个笔记本、每一个管道或每一个数据仓库。但对于需要血缘关系、刷新和内置数据质量的声明式转换,它们现在已成为 Microsoft Fabric 中一个合法的默认选择。
感谢阅读!
撰写人
查看 Nikola Ilic 的所有文章
数据架构
,
数据建模
数据科学
Microsoft Fabric
Sql
分享这篇文章
- 在 Facebook 上分享
- 在 LinkedIn 上分享
- 在 X 上分享
Towards Data Science 是一个社区出版物。提交你的见解以触达全球受众,并通过 TDS 作者支付计划获得报酬。
更新为你的实际提交 URL
为 TDS 写作
✦ 结束 CTA ✦