.create materialized-view

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

具体化视图是针对源表的聚合查询。 它代表单个 summarize 语句。

可以根据命令中 backfill 选项的说明,通过两种方式创建具体化视图:

从当前时间开始创建具体化视图:

  • 创建的具体化视图是空的。 它仅包括创建视图后引入的记录。 此类型的创建操作会立即返回,并且视图立即可供查询。

根据源表中的现有记录创建具体化视图:

  • 请参阅回填具体化视图
  • 创建过程可能需要很长时间才能完成,具体取决于源表中的记录数。 在回填完成之前,视图不可用于查询。
  • 使用此选项时,创建命令必须为 async。 可以使用 .show operations 命令监视执行。
  • 可以使用 .cancel operation 命令取消回填过程。

重要

对于大型源表,回填选项可能需要很长时间才能完成。 如果此过程在运行时暂时失败,系统不会自动进行重试。 之后必须重新执行创建命令。 有关详细信息,请参阅回填具体化视图

权限

此命令需要数据库管理员权限。 具体化视图的创建者将成为它的管理员。

语法

.create [async] [ifnotexists] materialized-view [ with (PropertyName = PropertyValue,...)] MaterializedViewName on table SourceTableName { Query }

详细了解语法约定

参数

客户 类型​​ 必需 说明
PropertyName、PropertyValue string 受支持属性列表中的一组属性(采用名称和值对形式)。
MaterializedViewName string ✔️ 具体化视图的名称。 视图名称不能与同一数据库中的表名或函数名冲突,并且必须遵循标识符命名规则
SourceTableName string ✔️ 定义视图的源表的名称。
查询 string ✔️ 具体化视图的查询定义。 有关详细信息和限制,请参阅查询参数部分。

注意

如果具体化视图已存在:

  • 如果指定了 ifnotexists 标志,则该命令将被忽略。 即使新定义与现有定义不匹配,也不会应用任何更改。
  • 如果未指定 ifnotexists 标志,则将返回错误。
  • 若要更改现有的具体化视图,请使用 .alter materialized-view 命令。

支持的属性

with (PropertyName = PropertyValue) 子句支持以下属性。 所有属性都是可选的。

名称 Type 说明
backfill bool 是要根据 SourceTable 中当前存在的所有记录创建视图 (true),还是从当前时间开始创建视图 (false)。 默认值为 false。 有关详细信息,请参阅回填具体化视图
effectiveDateTime datetime 仅在使用 backfill 时相关。 如果设置此项,则创建操作仅会回填在该日期/时间之后引入的记录。 backfill 也必须设置为 true。 应为此属性输入日期/时间文本,例如 effectiveDateTime=datetime(2019-05-01)
updateExtentsCreationTime bool 仅在使用 backfill 时相关。 如果此项设置为 true,则会在回填过程中根据日期/时间分组依据键来分配区创建时间。 有关详细信息,请参阅回填具体化视图
lookback timespan 仅对 arg_max/arg_min/take_any 具体化视图有效。 此属性限制需要重复项的时间段。 例如,如果在 arg_max 视图上指定了 6 小时的回溯,则新引入的记录与现有记录之间的重复数据删除将只考虑最长 6 小时前引入的记录。

回溯相对于 ingestion_time()。 如果具体化视图查询不保留 ingestion_time() 值,则无法对视图定义回溯。 请参阅具体化视图的限制和已知问题。 错误地定义回溯时段可能会导致具体化视图中出现重复项。 例如,如果一个特定键的记录在同一键的记录被引入 10 小时后引入,而回溯设置为 6 小时,则此键将是视图中的重复项。 在实现时查询时将应用回溯时段。
autoUpdateSchema bool 是否根据源表更改自动更新视图。 默认值为 false。 此选项仅对 arg_max(Timestamp, *)/arg_min(Timestamp, *)/take_any(*) 类型的视图(仅当列的参数为 * 时)有效。 如果将此选项设置为 true,则对源表所做的更改会自动反映在具体化视图中。
dimensionTables array 一个动态参数,其中包含视图中维度表的数组。 请参阅查询参数
文件夹 string 具体化视图的文件夹。
docString string 记录具体化视图的字符串。
allowMaterializedViewsWithoutRowLevelSecurity bool 允许在启用了行级安全策略的表上创建具体化视图。

警告

  • 如果对具体化视图的源表的更改或者数据的更改导致具体化视图查询与所需的具体化视图的架构不兼容,则系统会自动禁用具体化视图。
  • 若要避免此错误,具体化视图查询必须是确定性的。 例如,bag_unpackpivot 插件会导致架构不确定。
  • 当使用 arg_max(Timestamp, *) 聚合且 autoUpdateSchema 为 false 时,对源表的更改也可能导致架构不匹配。 可以通过将视图查询定义为 arg_max(Timestamp, Column1, Column2, ...) 或使用 autoUpdateSchema 选项来避免此错误。
  • 删除源表中的列时,使用 autoUpdateSchema 可能会导致不可恢复的数据丢失。
  • 使用 MaterializedViewResult 指标监视具体化视图的自动禁用。
  • 修复不兼容性问题后,应使用 enable materialized view 命令显式重新启用视图。

根据具体化视图创建具体化视图

仅当源具体化视图为 take_any(*) 聚合(重复数据删除)时,才能根据另一个具体化视图创建具体化视图。 有关详细信息,请参阅基于一个具体化视图创建另一个具体化视图示例

语法:

.create [async] [ifnotexists] materialized-view [ with (PropertyName = PropertyValue,...)] MaterializedViewName on materialized-view SourceMaterializedViewName { Query }

参数:

名称 类型​​ 必需 说明
PropertyName、PropertyValue string 受支持属性列表中的一组属性(采用名称和值对形式)。
MaterializedViewName string ✔️ 具体化视图的名称。 视图名称不能与同一数据库中的表名或函数名冲突,并且必须遵循标识符命名规则
SourceMaterializedViewName string ✔️ 定义了视图的源具体化视图的名称。
查询 string ✔️ 具体化视图的查询定义。

示例

  • 创建一个空的 arg_max 视图,该视图仅具体化从当前时间开始引入的记录:

    .create materialized-view ArgMax on table T
    {
        T | summarize arg_max(Timestamp, *) by User
    }
    
  • 使用 async 通过回填选项为每日聚合创建具体化视图:

    .create async materialized-view with (backfill=true, docString="Customer telemetry") CustomerUsage on table T
    {
        T 
        | extend Day = bin(Timestamp, 1d)
        | summarize count(), dcount(User), max(Duration) by Customer, Day 
    } 
    
  • 使用 backfilleffectiveDateTime 创建具体化视图。 视图是仅基于此日期/时间之后的记录创建的。

    .create async materialized-view with (backfill=true, effectiveDateTime=datetime(2019-01-01)) CustomerUsage on table T 
    {
        T 
        | extend Day = bin(Timestamp, 1d)
        | summarize count(), dcount(User), max(Duration) by Customer, Day
    } 
    
  • 创建一个具体化视图,该视图使用 6 小时回溯时段根据 EventId 列删除源表的重复数据。 仅针对在当前记录之前的 6 小时引入的记录进行重复数据删除。

    .create materialized-view with(lookback=6h) DeduplicatedTable on table T
    {
        T
        | summarize take_any(*) by EventId
    }
    
  • 创建基于前一 DeduplicatedTable 具体化视图的向下采样具体化视图:

    .create materialized-view DailyUsage on materialized-view DeduplicatedTable
    {
        DeduplicatedTable
        | summarize count(), dcount(User) by Day=bin(Timestamp, 1d)
    }
    
  • 定义可以在 summarize 语句之前包含其他运算符,只要 summarize 是最后一个运算符即可:

    .create materialized-view CustomerUsage on table T 
    {
        T 
        | where Customer in ("Customer1", "Customer2", "CustomerN")
        | parse Url with "https://contoso.com/" Api "/" *
        | extend Month = startofmonth(Timestamp)
        | summarize count(), dcount(User), max(Duration) by Customer, Api, Month
    }
    
  • 下面与维度表联接的具体化视图:

    .create materialized-view with (dimensionTables = dynamic(["DimUsers"])) EnrichedArgMax on table T
    {
        T
        | lookup DimUsers on User  
        | summarize arg_max(Timestamp, *) by User 
    }
    
    .create materialized-view with (dimensionTables = dynamic(["DimUsers"])) EnrichedArgMax on table T 
    {
        DimUsers | project User, Age, Address
        | join kind=rightouter hint.strategy=broadcast T on User
        | summarize arg_max(Timestamp, *) by User 
    }
    

备注

查询参数

以下规则限制具体化视图查询参数中使用的查询:

  • 该查询应引用作为具体化视图源的单个事实数据表。 它应包含单个 summarize 运算符,以及一个或多个聚合函数,这些函数由一个或多个 group by 表达式聚合。 summarize 运算符必须始终是查询中的最后一个运算符。

    仅包含单个 arg_max/arg_min/take_any 聚合的具体化视图可能比包含这些聚合以及其他聚合(例如 count/dcount/avg)的具体化视图性能更好。 这是因为某些优化仅与这类具体化视图相关。 当视图中包含混合聚合函数(“混合”的意思是 arg_max/arg_min/take_any 和其他聚合位于同一视图中)时,这些优化不适用。

  • 查询不应包含依赖于 now() 的任何运算符。 例如,查询不应具有 where Timestamp > ago(5d)。 对具体化视图使用保留策略来限制视图涵盖的时间段。

  • 具体化视图查询中不支持以下运算符:sorttop-nestedtoppartitionserialize

  • 具体化视图定义中不支持复合聚合。 例如,不要使用 SourceTableName | summarize Result=sum(Column1)/sum(Column2) by Id,而是将具体化视图定义为 SourceTableName | summarize a=sum(Column1), b=sum(Column2) by Id。 在进行视图查询期间运行 MaterializedViewName | project Id, Result=a/b。 可以将视图的必需输出(包括计算列 (a/b))封装在存储函数中。 请访问存储函数,而不是直接访问具体化视图。

  • 不支持跨群集和跨数据库查询。
  • 不支持引用 external_table()externaldata

  • 具体化视图查询不能包含任何需要模拟的标注。 具体而言,使用模拟的所有查询连接插件均不受允许。

  • 除了视图的源表之外,还允许查询引用一个或多个维度表。 必须在视图属性中显式调用维度表。 联接维度表时必须知道以下行为:

    • 视图的源表(事实数据表)中的记录仅具体化一次。 对维度表的更新不会对事实数据表中已处理的记录产生任何影响。

    • 事实数据表与维度表之间的不同引入延迟可能会影响视图结果。

      示例:视图定义包含一个与维度表的内联。 在具体化时,维度记录未完全引入,但已引入到事实数据表。 此记录会从视图中删除,不会再次处理。

      同样,如果联接是外部联接,则会处理事实数据表中的记录,并将其添加到视图,其中维度表列具有 null 值。 已添加到视图的记录(具有 null 值)不会再次处理。 它们在维度表的列中的值将保留为 null。

支持的聚合函数

支持以下聚合函数:

性能提示

  • 使用日期/时间分组依据键:使用日期/时间列作为分组依据键之一的具体化视图,比不这样做的具体化视图效率更高。 原因是仅当存在日期/时间分组依据键时才能应用某些优化。 如果添加日期/时间分组依据键不会更改聚合的语义,则建议添加它。 仅当日期/时间列对于每个唯一实体不可变时,才能执行此操作。

    例如,在以下聚合中:

        SourceTable | summarize take_any(*) by EventId
    

    如果 EventId 始终具有相同的 Timestamp 值,因而添加 Timestamp 不会更改聚合的语义,则最好将视图定义为:

        SourceTable | summarize take_any(*) by EventId, Timestamp
    

    提示

    日期/时间分组依据键中延迟到达的数据可能会对具体化视图的性能产生负面影响。 例如,假设具体化视图使用 bin(Timestamp, 1d) 作为其分组依据键之一,并且源表中新引入的记录具有旧 Timestamp 值。 这些记录可能会对具体化视图产生负面影响。

    如果希望将延迟到达的记录引入源表,请相应地调整具体化视图的缓存策略。 例如,如果预计将时间戳为 6 个月前的记录引入源表,则具体化过程将需要扫描前六个月的具体化视图。 如果此时间段处于冷缓存中,则具体化将遇到缓存未命中,这将对视图的性能产生负面影响。

    如果不希望出现这种延迟到达的记录,建议在具体化视图查询中筛选掉这些记录或将其时间戳值规范化为当前时间。

  • 定义回溯时段:如果适用于你的方案的话,添加 lookback 属性可以显著提高查询性能。 有关详细信息,请参阅支持的属性

  • 添加经常用于筛选的列作为分组依据键:按某个具体化视图分组依据键筛选时,具体化视图查询筛选器会得到优化。 如果你知道自己的查询模式经常按某个列进行筛选,而该列不会根据具体化视图中的唯一实体发生变化,那么,请将该列包含在具体化视图的分组依据键中。

    例如,具体化视图按 ResourceId 值公开 arg_max,而该值通常按 SubscriptionId 筛选。 假设 ResourceId 值始终属于同一个 SubscriptionId 值,请将具体化视图查询定义为:

    .create materialized-view ArgMaxResourceId on table FactResources
    {
        FactResources | summarize arg_max(Timestamp, *) by SubscriptionId, ResourceId 
    }
    

    上面的定义优先于以下定义:

    .create materialized-view ArgMaxResourceId on table FactResources
    {
        FactResources | summarize arg_max(Timestamp, *) by ResourceId 
    }
    
  • 在适当的情况下使用更新策略:具体化视图可以包含维度表中的转换、规范化和查找。 但是,我们建议将这些操作移动到更新策略。 仅保留具体化视图的聚合。

    例如,定义以下更新策略会更好:

    .alter-merge table Target policy update 
    @'[{"IsEnabled": true, 
        "Source": "SourceTable", 
        "Query": 
            "SourceTable 
            | extend ResourceId = strcat('subscriptions/', toupper(SubscriptionId), '/', resourceId)", 
            | lookup DimResources on ResourceId
            | mv-expand Events
        "IsTransactional": false}]'  
    

    并定义以下具体化视图:

    .create materialized-view Usage on table Events
    {
        Target 
        | summarize count() by ResourceId 
    }
    

    替代方法(将更新策略包含为具体化视图查询的一部分)的执行情况可能会更差,因此未被推荐:

    .create materialized-view Usage on table SourceTable
    {
        SourceTable
        | extend ResourceId = strcat('subscriptions/', toupper(SubscriptionId), '/', resourceId)
        | lookup DimResources on ResourceId
        | mv-expand Events
        | summarize count() by ResourceId
    }
    

提示

如果你需要最佳查询时间性能,但可以容忍某种程度的数据延迟,请使用 materialized_view() 函数

回填具体化视图

使用 backfill 属性创建具体化视图时,将会根据源表中可用的记录创建该具体化视图。 或者,如果你使用 effectiveDateTime,则会根据这些记录的子集创建具体化视图。

在后台,回填过程会将要回填的数据拆分成多个批次,并会执行多个引入操作来回填视图。 源表中的记录数太大时,此过程可能需要很长时间才能完成。 进程持续时间取决于数据库大小。 使用 .show operations 命令跟踪回填进度。

系统会重试回填过程中发生的暂时性故障。 如果所有重试次数已用完,则该命令将失败,并且需要手动重新执行创建命令。

当源表中的记录数超过 number-of-nodes X 200 million(有时甚至更少,具体取决于查询的复杂性)时,我们不建议使用回填。 可以改用通过移动区进行回填选项。

对于冷缓存中的数据,不支持使用回填选项。 如有必要,请增加用于创建视图的热缓存期限。 这可能需要横向扩展。

如果在创建视图发生失败,请尝试更改以下属性:

  • MaxSourceRecordsForSingleIngest:默认情况下,在回填期间,每个引入操作中的源记录数为每个节点 200 万条。 可以通过将此属性设置为所需的记录数来更改此默认值。 (该值是每个引入操作中的记录总数。)

    如果创建操作因内存限制或查询超时而失败,那么降低该值可能会解决问题。 提高该值可以加快视图创建速度(假设数据库能够在记录数超过默认值的情况下执行聚合函数)。

  • Concurrency:在回填过程中运行的引入操作以并发方式运行。 默认情况下,并发度为 min(number_of_nodes * 2, 5)。 可以设置此属性来提高或降低并发性。 建议仅在数据库的 CPU 较低时才增大此值,因为增大此值可能会大幅影响数据库的 CPU 消耗量。

例如,以下命令基于 2020-01-01 的数据回填具体化视图。 每个引入操作中的最大记录数为 300 万条。 该命令将以 2 并发性执行引入操作。

.create async materialized-view with (
        backfill=true,
        effectiveDateTime=datetime(2020-01-01),
        MaxSourceRecordsForSingleIngest=3000000,
        Concurrency=2
    )
    CustomerUsage on table T
{
    T
    | summarize count(), dcount(User), max(Duration) by Customer, bin(Timestamp, 1d)
} 

如果具体化视图包含日期/时间分组依据键,则回填过程支持根据日期/时间列来重写区创建时间。 这在某些情况下可能很有用,例如,在你希望在较新的记录之前删除较旧记录的情况下,因为保留策略基于区创建时间。 仅当视图包含使用 bin() 函数的日期/时间分组键时,才支持 updateExtentsCreationTime 属性。 例如,以下回填将根据 Timestamp 分组依据键分配创建时间:

.create async materialized-view with (
        backfill=true,
        updateExtentsCreationTime=true
    )
    CustomerUsage on table T
{
    T
    | summarize count() by Customer, bin(Timestamp, 1d)
} 

通过移动分片进行回填

通过移动区进行回填的选项基于现有表(不一定是具体化视图的源表)回填具体化视图。 实现回填的方式是将指定的表中的区移动到基础具体化视图表。 此过程意味着:

  • 指定的表中的数据应与具体化视图架构具有相同的架构。
  • 指定的表中的记录将按原样移动到视图。 假设根据具体化视图的定义删除记录中的重复数据。

例如,如果具体化视图具有以下聚合:

T | summarize arg_max(Timestamp, *) by EventId

则源表中用于“移动区”操作的记录应已按照 EventID 删除重复数据。

由于操作使用 .move extents,因此回填(已移动但未复制)期间将从指定的表中删除记录。

具体化视图中支持的聚合函数并非全部支持按移动盘区进行回填。 对于 avg()dcount() 之类的聚合,这种回填操作会失败,因为视图中存储的基础数据不同于聚合本身。

具体化视图仅根据指定的表进行回填。 默认情况下,对视图的源表中的记录进行具体化将从视图创建时开始。

如果具体化视图的源表不断引入数据,则使用“移动区”方法创建视图可能会导致丢失一些数据。 这是因为,在从准备要从中回填的表到创建视图的短时间内,引入到源表中的记录不会包含在具体化视图中。 若要处理这种情况,可将 source_ingestion_time_from 属性设置为基于源表的具体化视图的开始时间。

用例

通过移动区进行回填的选项在以下两种主要情况下可能很有用:

  • 如果你已有一个表,其中包含具体化视图的源数据(已删除重复数据),并且在创建视图后你不需要此表中的这些记录,因为你只使用具体化视图。

  • 当具体化视图的源表非常大时,由于上述限制,基于源表回填视图将无法顺利进行。 在这种情况下,可以使用 ingest from query 命令自行将回填进程回填到临时表中。 当临时表包含用于回填的所有记录时,请基于该表创建具体化视图。

还可以使用建议的业务流程工具之一。

示例:

  • 在以下示例中,表 DeduplicatedTable 包含每个 EventId 实例的单条记录,并将用作具体化视图的基线。 只有在视图创建时间之后引入 T 中的记录才会包含在具体化视图中。

    .create async materialized-view with (move_extents_from=DeduplicatedTable) MV on table T
    {
        T
        | summarize arg_max(Timestamp, *) by EventId
    } 
    
  • 如果 effectiveDateTime 属性与 move_extents_from 属性一起指定,则只有 DeduplicatedTableMaxCreatedOn 值大于 effectiveDateTime 的区才包含在回填中(已移动到具体化视图):

    .create async materialized-view with 
        (move_extents_from=DeduplicatedTable, effectiveDateTime=datetime(2019-01-01)) 
        MV on table T
    {
        T
        | summarize arg_max(Timestamp, *) by EventId
    } 
    
  • 以下示例演示如何在“通过移动区进行回填”选项中使用 source_ingestion_time_from 属性。 同时使用 source_ingestion_time_frommove_extents_from 表示从两个不同的源回填具体化视图:

    • move_extents_from 表:以下示例中的 DeduplicatedTable。 此表应包含所有要回填的历史数据。 可以选择性地使用 effectiveDateTime 属性来仅包含 DeduplicatedTableMaxCreatedOn 值大于 effectiveDateTime 的区。

    • 具体化视图的源表:以下示例中的 T。 此表的回填仅包含 ingestion_time() 值大于 source_ingestion_time_from 的记录。

      source_ingestion_time_from 属性应仅用于处理在从准备要从中回填的表 (DeduplicatedTable) 到创建视图的短时间内可能发生的数据丢失问题。 不要将此属性设置为很久以前的时间。 这会导致在具体化视图中以明显的滞后时间开始回填,使其难以赶上进度。

    以下示例假设当前时间为 2020-01-01 03:00。 表 DeduplicatedTableT 的已删除重复数据的表。 该表包含所有历史数据(已删除 2020-01-01 00:00 之前的所有重复数据)。 create 命令使用 DeduplicatedTable 通过移动区来回填具体化视图。 create 命令还包括 T 中自 2020-01-01 以来引入的所有记录。

    .create async materialized-view with (move_extents_from=DeduplicatedTable, source_ingestion_time_from=datetime(2020-01-01)) MV on table T
    {
        T
        | summarize arg_max(Timestamp, *) by EventId
    } 
    

取消具体化视图创建过程

使用回填选项时,可以取消具体化视图创建过程。 当创建过程所需时间太长,并且你想要停止创建时,此操作非常有用。

警告

运行此命令后,无法还原具体化视图。

无法立即取消创建进程。 取消命令会通知具体化停止,创建时会定期检查是否请求了取消。 取消命令会等待最长 10 分钟时间,直到具体化视图创建过程被取消,并报告取消是否已成功。

即使取消未在 10 分钟内成功完成,并且取消命令报告了失败,具体化视图也可能会稍后在创建过程中自行取消。 .show operations 命令指示操作是否已取消。

如果在发出 .cancel operation 命令时不再执行该操作,该命令将报告一个错误,指出此情况。

语法

.cancel operation operationId

详细了解语法约定

参数

客户 类型​​ 必需 说明
operationId guid ✔️ .create async materialized-view 命令返回的操作 ID。

输出

名称 Type 说明
OperationId guid .create materialized-view 命令的操作 ID。
操作 string 操作的类型。
StartedOn datetime 创建操作的开始时间。
CancellationState string 值为下列其中一个:Canceled successfully(已取消创建)、Cancellation failed(等待取消超时)、Unknown(视图创建操作不再运行,但未由此操作取消)。
ReasonPhrase string 取消操作失败的原因。

示例

.cancel operation c4b29441-4873-4e36-8310-c631c35c916e
OperationId 操作 StartedOn CancellationState ReasonPhrase
c4b29441-4873-4e36-8310-c631c35c916e MaterializedViewCreateOrAlter 2020-05-08 19:45:03.9184142 Canceled successfully

如果取消操作未在 10 分钟内完成,CancellationState 会指示失败。 然后可以取消创建。