具体化视图

适用于:✅Azure 数据资源管理器

具体化视图公开对源表或另一个具体化视图的聚合查询。

具体化视图始终返回聚合查询的最新结果(始终是全新的)。 查询具体化视图比直接对源表运行聚合的性能更高。

注意

为何使用具体化视图?

通过为常用聚合的具体化视图投资资源(数据存储、后台 CPU 周期),可以获得以下优势:

  • 性能提升: 对于相同的聚合函数,查询具体化视图通常比查询源表性能更好。

  • 时效性: 具体化视图查询始终返回最新结果,而不受上次进行具体化的时间的影响。 查询组合了视图的具体化部分和源表中尚未具体化的记录(delta 部分),始终提供最新结果。

  • 降低成本:与对源表执行聚合操作相比,查询具体化视图消耗的资源较少。 如果只需要聚合,则可以减少源表的保留策略。 此设置可减少源表的热缓存开销。

有关示例用例,请参阅具体化视图用例

具体化视图的工作原理

具体化视图由两个组件组成:

  • 具体化部分 - 一个包含源表中已处理的聚合记录的表。 该表始终按聚合的分组依据组合保存单个记录。
  • 增量 - 源表中尚未处理的新引入记录。

查询具体化视图会将具体化部分与增量部分组合起来,提供聚合查询的最新结果。 脱机具体化过程将增量中的新记录引入到具体化表,并更新现有记录。 如果增量和具体化部分之间的交集很大,并且有许多记录需要更新,这可能会对具体化过程产生负面影响。 请参阅监视具体化视图,了解如何排查此类情况。

具体化视图查询

可以通过两种方法查询具体化视图:

  • 查询整个视图:按名称查询具体化视图(与查询表类似)时,具体化视图查询会将视图的具体化部分与源表中尚未具体化 (delta) 的记录组合在一起。

    • 查询具体化视图时,会始终根据引入到源表的所有记录返回最新结果。 有关具体化视图中的具体化和非具体化部分的详细信息,请参阅具体化视图的工作原理
    • 此选项可能不会以最佳方式执行,因为它需要在查询时具体化 delta 部分。 在这种情况下,性能取决于视图的生存期和在查询中应用的筛选器。 具体化视图查询优化器部分包括在查询整个视图时提高查询性能的可能方法。
  • 仅查询具体化部分:查询该视图的另一种方法是使用 materialized_view() 函数。 此选项支持仅查询该视图的具体化部分,同时指定用户愿意容忍的最大延迟。

    • 此选项不保证返回最新记录,但与查询整个视图相比,此选项始终更加高效。
    • 此函数适用于你愿意舍弃一些时效性以提高性能的方案,例如,适用于遥测仪表板。

提示

仅对具体化部分进行查询的性能比查询整个视图的性能更好。 如果适用于你的用例,请始终使用 materialized_view() 函数。

  • 具体化视图可以参与跨群集或跨数据库查询,但不包括在通配符联合或搜索中。

    • 以下示例全都包括名为 ViewName 的具体化视图:
    cluster('cluster1').database('db').ViewName
    cluster('cluster1').database('*').ViewName
    database('*').ViewName
    database('DB*').ViewName
    database('*').materialized_view('ViewName')
    database('DB*').materialized_view('ViewName')
    
    • 以下示例不包括来自具体化视图的记录:
    cluster('cluster1').database('db').*
    database('*').View*
    search in (*)
    search * 
    

具体化视图查询优化器

查询整个视图时,具体化部分在查询期间与 delta 结合。 这包括聚合 delta 并将其与具体化部分联接。

  • 如果查询在具体化视图查询的分组依据键上包含筛选器,查询整个视图的性能会更好。 在.create materialized-view性能提示部分中查看有关如何根据你的查询模式创建具体化视图的更多提示。
  • 查询优化器会选择预计会提高查询性能的汇总/联接策略。 例如,有关是否对查询使用随机选择策略的决定基于 delta 部分中的记录数。 以下客户端请求属性提供对已应用的优化的一些控制。 可以通过具体化视图查询来测试这些属性,并评估它们对查询性能的影响。
客户端请求属性名称 类型 描述
materialized_view_query_optimization_costbased_enabled bool 如果此项设置为 false,则在具体化视图查询中禁用汇总/联接优化。 使用默认策略。 默认值为 true
materialized_view_shuffle dynamic 强制对具体化视图查询使用随机选择策略,并(选择性地)提供特定的键来作为随机选择依据。 请参阅以下示例

具体化视图上下文中的 ingestion_time() 函数

如果查询整个视图,则在具体化视图的上下文中使用时,ingestion_time() 函数会返回 null 值。 查询视图的具体化部分时,返回值取决于具体化视图的类型:

  • 在包含单个 arg_max()/arg_min()/take_any() 聚合的具体化视图中,ingestion_time() 等于源表中相应记录的 ingestion_time()
  • 在所有其他具体化视图中,ingestion_time() 的值大约是具体化时间(请参阅具体化视图的工作原理)。

示例

  1. 查询整个视图。 包括源表中的最新记录:

    ViewName
    
  2. 仅查询该视图的具体化部分,而不考虑其上次进行具体化的时间。

    materialized_view("ViewName")
    
  3. 查询整个视图,并提供提示以使用 shuffle 策略。 包括源表中的最新记录:

    • 示例 #1:基于 Id 列随机执行(类似于使用 hint.shufflekey=Id):
    set materialized_view_shuffle = dynamic([{"Name" : "ViewName", "Keys" : [ "Id" ] }]);
    ViewName
    
    • 示例 #2:基于所有键随机执行(类似于使用 hint.strategy=shuffle):
    set materialized_view_shuffle = dynamic([{"Name" : "ViewName" }]);
    ViewName
    

性能注意事项

可能会影响具体化视图运行状况的主要参与者有:

  • 群集资源: 与群集上运行的任何其他进程一样,具体化视图使用群集中的资源(CPU、内存)。 如果群集超载,将具体化视图添加到其中可能会导致群集性能下降。 可使用群集运行状况指标监视群集的运行状况。 优化的自动缩放目前不将正在考虑的具体化视图运行状况作为自动缩放规则的一部分。
  • 与具体化数据重叠:在具体化期间,自上次具体化后引入到源表中的所有新记录(增量)会被处理并具体化到视图中。 新记录与已具体化记录之间的交集越大,具体化视图的性能就越差。 如果要更新的记录数(例如,在 arg_max 视图中的记录数)是源表的一小部分,则具体化视图的效果最佳。 如果所有或大多数具体化视图记录需要在每个具体化循环中进行更新,则具体化视图可能不会很好地执行。

  • 引入速率: 在具体化视图的源表中,对数据量或引入速率没有硬编码限制。 但是,具体化视图的建议引入速率不超过 1-2GB/秒。采用更高的引入速率可能仍然可以很好地执行。 性能取决于数据库大小、可用资源以及与现有数据的交集量。

  • 群集中的具体化视图数: 上述注意事项适用于在群集中定义的每个单独的具体化视图。 每个视图都使用其自己的资源,许多视图会彼此争用可用资源。 虽然群集中的具体化视图数量没有硬编码限制,但在定义许多具体化视图的情况下,群集可能无法处理所有具体化视图。 如果在群集中有多个具体化视图,则可以调整容量策略。 增加策略中 ClusterMinimumConcurrentOperations 的值可同时运行更多具体化视图。
  • 具体化视图定义:必须根据可获得最佳查询性能的查询最佳做法定义具体化视图定义。 有关详细信息,请参阅 create 命令性能提示

基于具体化视图的具体化视图

如果源具体化视图是重复数据删除视图,则可以对另一个具体化视图创建具体化视图。 具体来说,源具体化视图的聚合必须为 take_any(*),以便对源记录进行重复数据删除。 第二个具体化视图可以使用任何支持的聚合函数。 有关如何在具体化视图上创建具体化视图的具体信息,请参阅 .create materialized-view命令

提示

在查询通过另一个具体化视图定义的具体化视图时,建议仅使用 materialized_view() 函数查询具体化部分。 当两个视图都没有完全具体化时,查询整个视图的性能不佳。 有关详细信息,请参阅具体化视图查询