指标视图的物化

重要

此功能目前以公共预览版提供。

指标视图的物化通过使用物化视图预先计算聚合,从而加速查询。 Lakeflow Spark 声明性管道协调给定指标视图的用户定义具体化视图。 在查询时,查询优化器使用自动聚合感知查询匹配(查询重写)将查询路由到最佳具体化视图。 可以像往常一样查询指标视图,无需进行额外的手动操作。 Databricks 会刷新物化结果以保持其最新状态,并选择查询哪个物化结果,以更低的成本实现更快的查询。

物化的工作原理

指标视图的具体化涉及两个阶段:首先是定义具体化,然后是对其进行查询。

定义阶段

使用具体化 定义指标视图 时,可以在指标视图 YAML 中指定字段、度量值和刷新计划。 从该定义中,Databricks 创建一个 托管的 Lakeflow Spark 声明性管道 ,用于生成和维护具体化视图。

指标视图定义和具体化管道

这会使指标定义与存储方式分开:

  • 指标视图 是一个 Unity 目录对象,用于定义指标的字段、度量值和联接,以及具体化配置(计划和粒度)。 这是指标含义的单一事实来源。
  • 管道 将定义具体化为一个或多个具体化视图,每个视图都以特定粒度预先计算。 Databricks 会在查询时选择读取哪一个。

查询执行

运行 SELECT ... FROM <metric_view>时,查询优化器使用聚合感知查询重写来优化性能:

通过面向聚合的重写执行查询

  • 快速路径:当存在合适的物化时,从预先计算的物化视图读取。
  • 回退路径:在没有合适的具体化可用时直接从源数据读取数据。

查询优化器通过在具体化数据和源数据之间进行选择来自动平衡性能和新鲜度。 无论优化器使用的路径如何,你都会以透明方式接收结果。 有关针对指标视图运行查询的详细信息,请参阅 查询指标视图

要求

若要对指标视图使用具体化,请执行以下步骤:

  • 工作区必须启用无服务器计算。 这是运行 Lakeflow Spark 声明性管道所必需的。
  • 运行 Databricks Runtime 17.3 或更高版本的 SQL 仓库或计算资源。

配置参考

您可以在指标视图 YAML 定义的顶层 materialization 字段中配置物化。 此字段设置查询重写 mode(始终为 relaxed)、可选的刷新 schedule,以及要维护的 materialized_views 列表。 每个具体化视图要么 aggregated 是(预先计算特定的维度和度量值),要么 unaggregated (具体化完整的数据模型)。

有关完整的逐字段规范,包括必填字段和可选字段、允许的值和 schedule 子句限制,请参阅 具体化

示例定义

以下示例定义了一个指标视图,其中包含一个未聚合物化和两个聚合物化:

version: 1.1

source: prod.operations.orders_enriched_view

filter: revenue > 0

fields:
  - name: category
    expr: substring(category, 5)

  - name: color
    expr: color

measures:
  - name: total_revenue
    expr: SUM(revenue)

  - name: number_of_suppliers
    expr: COUNT(DISTINCT supplier_id)

materialization:
  schedule: every 6 hours
  mode: relaxed

  materialized_views:
    - name: baseline
      type: unaggregated

    - name: revenue_breakdown
      type: aggregated
      dimensions:
        - category
        - color
      measures:
        - total_revenue

    - name: suppliers_by_category
      type: aggregated
      dimensions:
        - category
      measures:
        - number_of_suppliers

查询重写模式

relaxed 模式下,自动查询重写仅验证候选具体化视图是否具有为查询提供服务的必要字段和度量值。

跳过以下检查:

  • 新鲜度:它不会验证物化结果是否为最新。
  • SQL 设置:不会验证诸如 TIMEZONEANSI_MODE 等设置是否匹配。
  • 确定性:它不验证具体化结果是否完全确定。

与物化匹配的查询使用上次刷新的结果。 不匹配的查询回退到源并返回实时数据。 因此,数据新鲜度可能会因查询是否有资格重写而有所不同。 为确保一致性,请将物化刷新计划与源管道保持同步。 例如,如果数据源通过批处理管道每日更新,请将物化刷新安排在该管道完成后执行。 或者,使用未聚合物化来确保所有查询都从同一个快照读取。

如果指标视图或其任何源表使用了以下任一项,则无法创建物化:

  • 行级别安全性(RLS)列级掩码(CLM)。 预计算结果可能会绕过本应在查询时实施的针对每个用户的访问控制。

  • 依赖于调用者的表达式,其结果会根据运行查询的人员(例如, current_user()is_member()) 进行更改。 物化结果只需预先计算一次,便可供共享使用,因此如果将其提供给其他用户,返回的结果可能不正确或不安全。

当您创建、修改或刷新物化视图时,Databricks 会验证此限制。 这些操作因错误状况 METRIC_VIEW_MATERIALIZATION_WITH_INVOKER_DEPENDENT_EXPRESSIONS_NOT_SUPPORTEDSQLSTATE 42K0E)而失败。 请参阅 METRIC_VIEW_MATERIALIZATION_WITH_INVOKER_DEPENDENT_EXPRESSIONS_NOT_SUPPORTED

指标视图的实体化类型

以下部分介绍了可用于指标视图的具体化视图的类型,并提供有关为数据源和查询模式选择适当配置的指导。

聚合类型

此类型会针对指定的度量值和字段组合预先计算聚合结果,以实现有针对性的覆盖。

当有经常查询的特定维度和度量值组合时,请使用聚合类型。 使用聚合具体化时,将应用 完全匹配汇总匹配 策略,从而为这些模式提供最佳查询性能。

为获得最佳聚合

  • GROUP BY 子句中包含最常用的维度。
  • 包括任何潜在的筛选器列(查询时使用的 WHERE 列)。
  • 按照查询所需的最细粒度层级进行物化。 例如,(region, sku, event_day) 处的物化可以用于以下所有用途:
    • GROUP BY region
    • GROUP BY region, event_month
    • GROUP BY skuWHERE region = 'US'
  • 避免使用过于精细的维度,以免产生大量仅包含一行的组(例如,精确到毫秒的原始时间戳)。 这样做没有任何好处,还会增加存储占用。
  • 监视非累加性度量值。 无法从部分结果(例如,COUNT(DISTINCT)MEDIAN和百分位)重新聚合非累加性度量值,并且需要与具体化完全匹配。

单个聚合只能为匹配其特定维度(完全匹配)或维度子集(汇总匹配)的查询提供服务。 Databricks 建议为不同的查询形状创建多个聚合具体化。

未聚合类型

与聚合类型相比,此类型会实体化整个未聚合数据模型(即 sourcejoinsfilterfields 字段),以更小的性能开销提供更广的覆盖范围。

如果存在以下任一情况,请使用未聚合类型:

  • 您的指标视图涉及昂贵的源数据转换或联接。
  • 查询模式不可预知或不同。
  • 查询指标视图的所有用户都必须在数据中看到一致性。

使用未聚合的物化结果后,高开销的源视图和联接只需在刷新时计算一次,而不必在每次查询时都重新计算。 当聚合物化和未聚合物化同时存在时,Databricks 会根据未聚合物化计算聚合物化。 这提供一致的快照,并避免对源进行冗余重新计算。 无论查询形状如何,未聚合的匹配始终符合条件,但受 查询重写模式中所述的限制。

当源是没有选择性过滤条件的直接表引用时,未聚合的物化并没有帮助。 在这种情况下,它相比直接查询源没有任何优势。

自动查询重写

查询指标视图时,查询重写会自动将查询路由到最佳可用具体化。 它使用三种查询重写策略:完全匹配、汇总匹配和未聚合的匹配。

聚合感知查询重写

查询会自动在最佳具体化上运行,而不是使用此算法的基表:

  1. 首先,查询优化器会尝试进行精确匹配。
  2. 如果没有精确匹配,查询优化器会尝试进行汇总级匹配。
  3. 如果没有汇总匹配,且存在未聚合的物化结果,则查询优化器会尝试进行未聚合匹配。
  4. 如果没有未聚合的匹配项,查询将从源表直接读取。

以下部分介绍了每个策略的工作原理。

查询重写匹配策略

注释

具体化必须在查询重写生效之前完成具体化。

完全匹配

该查询要求的正是物化时预先计算好的内容。 查询重写将读取存储的结果,无需额外工作,从而实现快速结果。

若要符合完全匹配条件,

  • 查询的 GROUP BY 表达式必须与具体化维度完全匹配。
  • 查询的度量值必须是具体化度量值的子集。

例如,具体化具有维度 [region, order_date] 和度量值 [total_revenue, order_count]。 按 regionorder_date 分组并请求 total_revenue 的查询是精确匹配,因为维度相同,并且该度量值已预先计算。

汇总匹配

该查询要求的汇总粒度比预先计算的结果更粗。 优化器读取预计算结果,并将其重新聚合到查询所需的级别。

若要满足汇总匹配条件:

  • 较粗粒度:查询按比物化结果更少的维度分组,或采用比物化结果更粗的时间粒度。
  • 所有度量值都是累加性的:查询要求的每个度量值都必须是一个可以通过组合部分结果(例如 SUMSUM,s 或 MAXMAXes)来正确重新计算的度量值。 MEDIAN 无法向上汇总,因为它依赖于组分布。
  • 任何参与的筛选器都必须是确定性表达式:如果查询具有子 WHERE 句,筛选器必须始终为相同的输入生成相同的结果。 例如, WHERE region = 'US' 是确定性的,但表达式(例如 rand()uuid() 不是)。

汇总匹配不符合非累加性度量值的条件,因为它们无法从部分结果中正确重新聚合。 请参阅 累加度量值

例如,使用具有相同维度 [region, order_date] 和度量值 [total_revenue, order_count] 的物化时,仅按 region 分组并请求 total_revenue 的查询是一个汇总匹配。 查询所需的维度少于已物化的维度,因此引擎会将每日总计汇总为区域级总计。

累加性度量值

如果某个度量的聚合结果可以通过基于现有聚合物化结果再次聚合来正确重新计算,则该度量是可加的。 这是汇总匹配的核心要求。

任何使用 DISTINCT 的聚合(例如 COUNT(DISTINCT)SUM(DISTINCT))都是非可加的,无法向上汇总。

以下函数是累加函数:

  • SUM
  • COUNT
  • MIN
  • MAX
  • BIT_AND
  • BIT_OR
  • BIT_XOR
  • BOOL_AND
  • BOOL_OR

其他限制适用于累加性度量值:

  • 度量值定义必须仅包含一个聚合函数。 定义中组合了多个聚合(例如,sum(cost) + min(revenue))的度量值无法进行汇总匹配。
  • 如果度量值定义包含子 FILTER 句,则它必须是确定性的。
  • 度量值不能是窗口度量值(例如,使用窗口块定义的 7 天滚动总计或同比比较)。

未整合的匹配

该查询未匹配任何预先计算的聚合结果,但昂贵的预处理工作(联接和过滤)已完成。 查询重写基于未聚合物化结果的预准备数据集,而不是回到源表。

如果存在未聚合的物化结果,则在回退到源数据之前,此策略始终可以作为回退选项。 任何查询形状都可以使用它,但受 查询重写模式中所述的限制的约束。

例如,查询按 category 分组,并请求返回 unique_customers,但没有任何聚合物化结果包含这些字段和度量值。 但是,已存在一个未聚合的物化结果,其中经过联接和筛选的数据集已准备就绪。 查询优化器从该准备的数据集读取并在查询时运行 GROUP BY category, COUNT(DISTINCT customer_id) ,而不是从头开始重新联接原始表。

验证查询是否使用具体化视图

可通过两种方法检查查询是否使用具体化视图:

  • 对您的查询运行 EXPLAIN EXTENDED 以查看查询计划。 如果命中了该具体化结果,则叶节点会包含 __materialization_mat_<pipeline ID>___metric_view_mat_ 以及 YAML 文件中该具体化的名称。
  • 查看查询配置文件,如下所示。

显示物化使用情况的查询概要

物化生命周期

本部分解释了如何在整个生命周期内创建、管理和更新物化。

创建和修改

创建或修改指标视图(使用 CREATEALTER或目录资源管理器)时,指标视图定义会立即更新。 物化视图通过托管管道在后台异步刷新。

  • 创建时:如果指标视图包含物化,Databricks 将创建一个管道并立即触发初始刷新。 在刷新进行期间,指标视图仍然可以查询;查询会回退到源数据,直到物化结果完全创建完成。
  • 修改时:仅在首次启用物化时才会触发刷新。 在下次刷新完成之前,现有具体化不会用于查询重写。

更改具体化计划不会触发刷新。

如果没有计划,管道会在创建时运行初始更新,但必须手动触发后续刷新,否则数据将过时。 Databricks 建议始终定义计划,以便数据保持新鲜,除非要测试或原型制作。

请参阅 手动刷新 ,以更好地控制刷新行为。

检查基础管道

指标视图的具体化是使用 Lakeflow Spark 声明性管道实现的。 可以通过两种方式访问管道:

  • 在目录资源管理器中:指标视图的 “概述 ”选项卡包括 “刷新计划 ”标题下的直接链接。 若要了解如何访问目录资源管理器,请参阅什么是目录资源管理器?
  • 使用 SQL:运行 DESCRIBE EXTENDED。 “ 刷新信息” 部分包含管道链接和当前刷新状态。
DESCRIBE EXTENDED my_metric_view;

示例输出:

-- Returns additional metadata such as parent schema, owner, access time etc.
> DESCRIBE EXTENDED my_metric_view;
                      col_name                       data_type    comment
 ------------------------------- ------------------------------ ----------
                           ...                             ...        ...

 # Detailed Table Information
                           ...                             ...

                      Language                            YAML
              Table properties                             ...
 # Refresh Information
         Latest Refresh Status                       Succeeded
                Latest Refresh                     https://...
              Refresh Schedule                   EVERY 6 HOURS

手动刷新

从指向 Lakeflow Spark 声明式管道页面的链接,可以手动启动管道更新,以更新材质化内容。 还可以使用以下 SQL 命令触发手动刷新:

REFRESH MATERIALIZED VIEW <metric-view-name>

增量刷新

具体化视图尽可能使用增量刷新,并具有与有关数据源和计划结构的标准具体化视图相同的限制。

有关先决条件和限制的详细信息,请参阅 具体化视图的增量刷新

账单管理

刷新具体化视图会产生 Lakeflow Spark 声明性管道使用费。 若要查找管道的 DBU 消耗量,请参阅无服务器管道的 DBU 消耗量是多少?

已知限制

以下限制适用于指标视图的物化:

  • 为指标视图创建具体化后,无法更改所有者。
  • Databricks 不支持具体化指标视图的组所有权。
  • 只有完全匹配策略才适用于具有一对多联接的指标视图。