异步物化视图故障排除

本文为您介绍如何检查异步物化视图,并解决在使用时遇到的问题。

检查异步物化视图

为了全面了解正在使用的异步物化视图,您可以检查它们的工作状态、刷新历史和资源消耗情况。

检查工作状态

您可以使用SHOW MATERIALIZED VIEWS命令来检查异步物化视图的工作状态。

  • 语法

    SHOW MATERIALIZED VIEWS
    [FROM db_name]
    [
    WHERE NAME { = "mv_name" | LIKE "mv_name_matcher"}
    ]

    参数

    必选

    说明

    db_name

    物化视图所属的数据库名称。如果不指定该参数,则默认使用当前数据库。

    mv_name

    用于精确匹配的物化视图名称。

    mv_name_matcher

    用于模糊匹配的物化视图名称 matcher。

    在返回的所有信息中,您可以关注以下字段:

    • is_active:物化视图的状态是否为Active状态。只有处于Active状态的物化视图才能用于查询加速和改写。

    • last_refresh_state:最近一次刷新的状态,包括PENDING(等待中)、RUNNING(运行中)、FAILED(失败)和SUCCESS(成功)。

    • last_refresh_error_message:上次刷新失败的原因。如果物化视图状态不为Active状态,会记录相关的错误信息。

    • rows:物化视图中的数据行数。请注意,这个值可能与物化视图的实际行数不同,因为更新可能有延迟。

  • 示例

    SHOW MATERIALIZED VIEWS FROM test_db WHERE NAME LIKE 'mv_pred_2';

查看刷新历史

您可以通过查询information_schema数据库中的task_runs表来查看异步物化视图的刷新历史。在返回的所有信息中,您可以关注以下字段:

  • CREATE_TIMEFINISH_TIME:刷新任务的开始和结束时间。

  • STATE:刷新任务的状态,包括PENDING(等待中)、RUNNING(运行中)、FAILED(失败)和SUCCESS(成功)。

  • ERROR_MESSAGE:刷新任务失败的原因。

示例如下。

USE test_db;
SELECT * FROM information_schema.task_runs WHERE task_name ='mv-112517'

监控资源消耗情况

您可以在刷新任务执行期间或完成之后监控和分析异步物化视图所消耗的资源。

刷新任务执行期间监控资源消耗

刷新任务执行期间,您可以使用SHOW PROC '/current_queries';实时监控其资源消耗情况。

在返回的所有信息中,您可以关注以下字段:

  • ScanBytes:扫描的数据大小。

  • ScanRows:扫描的数据行数。

  • MemoryUsage:使用的内存大小。

  • CPUTime:CPU时间成本。

  • ExecTime:查询的执行时间。

刷新任务完成后分析资源消耗

在刷新任务完成后,您可以通过Query Profile来分析其资源消耗情况。详情请参见Query Profile介绍

当异步物化视图正在刷新时,会执行INSERT OVERWRITE语句。您可以检查相应的Query Profile,以分析刷新任务所消耗的时间和资源。

在返回的所有信息中,您可以关注以下指标:

  • Total:查询消耗的总时间。

  • QueryCpuCost:查询的总CPU时间成本。CPU时间成本会对并发进程进行聚合。因此,该指标的值可能大于查询的实际执行时间。

  • QueryMemCost:查询的总内存成本。

  • 其他针对各个运算符的特定指标,比如连接运算符和聚合运算符。

验证查询是否被改写

您可以通过使用EXPLAIN查看查询计划,以检查查询是否可以被异步物化视图重写。

如果查询计划中的SCAN指标显示了相应物化视图的名称,那么该查询已经被物化视图重写。

语法

EXPLAIN [ LOGICAL | VERBOSE | COSTS ] <query>
说明

执行计划详细程度:EXPLAIN LOGICAL < EXPLAIN < EXPLAIN VERBOSE < EXPLAIN COSTS。

通常情况下使用EXPLAIN即可,EXPLAIN VERBOSE和EXPLAIN COSTS会打印大量冗余信息,主要用于调试计划。

参数

说明

LOGICAL

显示简要的逻辑执行计划。

VERBOSE

显示详细的逻辑执行计划,包括数据类型,nullable信息,优化策略等。

COSTS

显示详细的逻辑执行计划,包括统计信息。

query

需要查看执行计划的查询语句。

示例一:查询被物化视图重写

  1. 建库建表,并导入数据。

    CREATE DATABASE IF NOT EXISTS test_db;
    use test_db;
    CREATE TABLE customer (
      c_custkey     INT(11)     NOT NULL,
      c_name        VARCHAR(26) NOT NULL,
      c_address     VARCHAR(41) NOT NULL,
      c_city        VARCHAR(11) NOT NULL,
      c_nation      VARCHAR(16) NOT NULL,
      c_region      VARCHAR(13) NOT NULL,
      c_phone       VARCHAR(16) NOT NULL,
      c_mktsegment  VARCHAR(11) NOT NULL
    ) ENGINE=OLAP
    DUPLICATE KEY(c_custkey)
    DISTRIBUTED BY HASH(c_custkey) BUCKETS 12;
    
    INSERT INTO test_db.customer
    WITH LABEL insert_load_customer
     VALUES
    (1, 'Customer A', '123 Elm Street', 'New York', 'USA', 'North America', '555-1234', 'AUTOMOBILE'),
    (2, 'Customer B', '456 Oak Avenue', 'Los Angeles', 'USA', 'North America', '555-5678', 'BUILDING'),
    (3, 'Customer C', '789 Pine Blvd', 'Chicago', 'USA', 'North America', '555-9012', 'FURNITURE'),
    (4, 'Customer D', '321 Maple Drive', 'Houston', 'USA', 'North America', '555-3456', 'MACHINERY'),
    (5, 'Customer E', '654 Cedar Court', 'Phoenix', 'USA', 'North America', '555-7890', 'HOUSEHOLD');
  2. 创建物化视图。

    use test_db;
    CREATE MATERIALIZED VIEW `mv_agg` (`c_custkey`)
    DISTRIBUTED BY RANDOM
    REFRESH ASYNC
    PROPERTIES (
    "replication_num" = "3",
    "replicated_storage" = "true",
    "storage_medium" = "HDD"
    )
    AS SELECT `customer`.`c_custkey`
    FROM `test_db`.`customer`
    GROUP BY `customer`.`c_custkey`;
  3. 查看查询计划。

    use test_db;
    EXPLAIN LOGICAL SELECT `customer`.`c_custkey`
    FROM `test_db`.`customer`
    GROUP BY `customer`.`c_custkey`;

    返回结果如下。SCAN指标显示了物化视图的名称为mv_agg,表示该查询已经被物化视图重写。

    image

示例二:禁用查询重写

如果禁用了查询重写功能,StarRocks将采用常规的查询计划。执行以下查询。

SET enable_materialized_view_rewrite = false;
EXPLAIN LOGICAL SELECT `customer`.`c_custkey`
  FROM `test_db`.`customer`
  GROUP BY `customer`.`c_custkey`;

返回结果如下。SCAN指标显示查询基表customer

image

诊断并解决故障

以下列出了在使用异步物化视图时可能遇到的一些常见问题,以及相应的解决方案。

创建异步物化视图失败

如果无法创建异步物化视图,即无法执行CREATE MATERIALIZED VIEW语句,您可以从以下几个方面着手解决。

  • 检查是否误用了创建同步物化视图的SQL语句。

    StarRocks提供了两种不同的物化视图:同步物化视图和异步物化视图。

    创建同步物化视图时使用的基本SQL语句如下:

    CREATE MATERIALIZED VIEW <mv_name> 
    AS <query>

    与之相比,创建异步物化视图时使用的SQL语句包含更多参数:

    CREATE MATERIALIZED VIEW <mv_name> 
    REFRESH ASYNC -- 异步物化视图的刷新策略。
    DISTRIBUTED BY HASH(<column>) -- 异步物化视图的数据分布策略。
    AS <query>

    除了SQL语句之外,这两种物化视图之间的主要区别在于,异步物化视图支持StarRocks提供的所有查询语法,而同步物化视图只支持有限的聚合函数。

  • 检查是否指定了正确的PARTITION BY列。

    在创建异步物化视图时,您可以为其指定分区策略,从而在更细粒度的级别上刷新物化视图。

    目前,StarRocks仅支持单列分区列,且只支持Range Partition。您可以在分区列使用date_trunc()函数进行上卷以更改分区策略的粒度级别。除此之外不支持任何其他表达式。

  • 检查您是否具有创建物化视图所需的权限。

    在创建异步物化视图时,您需要所有查询对象(表、视图、物化视图)的SELECT权限。当查询中使用UDF时,您还需要函数的USAGE权限。

物化视图刷新失败

如果物化视图刷新失败,即刷新任务的状态不是SUCCESS,您可以从以下几个方面着手解决:

  • 检查是否采用了不合适的刷新策略。

    默认情况下,物化视图在创建后会立即刷新。然而,在v2.5及早期版本中,采用MANUAL刷新策略的物化视图在创建后不会自动刷新。您必须使用REFRESH MATERIALIZED VIEW命令手动刷新。

  • 检查刷新任务是否超出了内存限制。

    通常情况下,当异步物化视图涉及大规模的聚合或连接计算时,会大量消耗内存资源。要解决这个问题,您可以:

    • 为物化视图指定分区策略,实现细粒度的刷新。

    • 为刷新任务启用中间结果落盘功能。从v3.1版本开始,StarRocks支持将物化视图刷新任务的部分中间结果落盘。执行以下语句启用中间结果落盘功能。

      -- 在创建物化视图时定义属性。
      CREATE MATERIALIZED VIEW mv1 
      REFRESH ASYNC
      PROPERTIES ( 'session.enable_spill'='true' )
      AS <query>;
      
      -- 为已有物化视图添加属性。
      ALTER MATERIALIZED VIEW mv2 SET ('session.enable_spill' = 'true');

物化视图刷新超时

较大的物化视图可能因为刷新任务超过超时时间而无法刷新,通常有以下几种解决方案。

  • 为物化视图指定分区策略,实现细粒度的刷新。

    创建分区物化视图所描述,对物化视图进行分区可以实现增量构建与刷新,能够规避在初始刷新时占用太多资源的问题。

  • 设置更大的超时时间。

    v3.2之前版本中,物化视图刷新任务的默认超时时间为5分钟,v3.2版本之后默认为1小时。当遇到超时异常时,可以执行以下命令,尝试修改超时时间。

    ALTER MATERIALIZED VIEW mv2 SET ( 'session.query_timeout' = '4000' );
  • 分析物化视图性能瓶颈。

    如果物化视图计算复杂,其本身计算耗时就会很久。您可以通过Query Profile分析性能瓶颈,并进行优化:

    1. 通过查询information_schema.task_runs获取刷新任务的query_id

    2. 通过上述的query_id,获取并分析其Query Profile。详情请参见Query Profile介绍

物化视图不可用

如果物化视图无法改写查询或刷新,且物化视图的is_active状态为false,可能是由于基表发生Schema Change。要解决这个问题,您可以通过执行以下语句,手动将物化视图状态设置为Active:

ALTER MATERIALIZED VIEW mv1 ACTIVE;

如果设置没有生效,您需要删除该物化视图并重新创建。

物化视图刷新任务占用过多资源

如果您发现刷新任务正在使用过多的系统资源,您可以从以下几个方面着手解决:

  • 检查创建的物化视图是否过大。

    如果您Join了多张表,导致了大量的计算,刷新任务将占用大量资源。要解决这个问题,您需要评估物化视图的大小并重新规划创建。

  • 检查刷新间隔是否过于频繁。

    如果物化视图采用了固定间隔刷新的策略,您可以调低刷新频率解决问题。如果刷新任务是由基表中的数据变更触发的,频繁的数据导入操作也可能导致此问题。要解决这个问题,您需要为物化视图定义合适的刷新策略。

  • 检查物化视图是否已分区。

    未分区的物化视图在刷新时可能消耗大量资源,因为StarRocks每次都会刷新整个物化视图。要解决这个问题,您需要为物化视图指定分区策略,实现细粒度的刷新。

要停止占用过多资源的刷新任务,您可以:

  • 将物化视图状态设置为Inactive,以停止所有刷新任务:

    ALTER MATERIALIZED VIEW mv1 INACTIVE;
  • 通过CANCEL REFRESH MATERIALIZED VIEW终止正在运行的刷新任务。

    CANCEL REFRESH MATERIALIZED VIEW mv1;

物化视图无法改写查询

如果物化视图无法改写相关查询,您可以从以下几个方面着手解决。

  • 通过TRACE诊断改写失败原因。

    StarRocks提供了TRACE命令来诊断物化视图无法改写的原因:

    • TRACE LOGS MV <query>:v3.2之后版本提供,用于分析详细的改写过程和改写失败的原因。

    • TRACE REASON MV <query>:v3.2.8之后版本提供,提供精简的改写失败原因。

    示例如下。

    TRACE REASON MV SELECT SUM(c1) FROM `glue_ice`.`iceberg_test`.`ice_test3`;
  • 检查物化视图和查询是否匹配。

    • StarRocks使用基于结构而非基于文本的匹配技术来匹配物化视图和查询。因此,并不是当查询与物化视图看起来一样时就一定可以改写查询。

    • 物化视图只支持重写SPJG(Select/Projection/Join/Aggregation)类型的查询,不支持改写涉及窗口函数、嵌套聚合或Join加聚合的查询。

    • 物化视图无法重写Outer Join中包含复杂的Join谓词的查询。例如,在类似A LEFT JOIN B ON A.dt > '2023-01-01' AND A.id = B.id的情况下,建议您将JOIN ON子句中的谓词在WHERE子句中指定。

    有关物化视图查询重写的限制信息,请参见使用限制

  • 检查物化视图的状态是否为Active。

    StarRocks在改写查询之前会检查物化视图的状态。只有当物化视图的状态为Active时,查询才能被改写。要解决这个问题,您可以通过执行以下语句手动将物化视图的状态设置为Active。

    ALTER MATERIALIZED VIEW mv1 ACTIVE;
  • 检查物化视图是否满足数据一致性要求。

    StarRocks会检查物化视图与基表数据的一致性。默认情况下,只有当物化视图中的数据为最新时,才能重写查询。要解决这个问题,您可以:

    • 为物化视图添加PROPERTIES('query_rewrite_consistency'='LOOSE')禁用一致性检查。

    • 为物化视图添加PROPERTIES('mv_rewrite_staleness_second'='5')来容忍一定程度的数据不一致。只要上次刷新在该时间间隔之内,无论基表中的数据是否发生变化,查询都可以被重写。

    • 检查物化视图的查询语句是否缺少输出列。

      为了改写范围和点查询,您必须在物化视图的查询语句的SELECT表达式中指定过滤所用的谓词。您需要检查物化视图的SELECT语句,以确保其含有查询中WHEREORDER BY子句中引用的列。

    示例1:物化视图mv1使用了嵌套聚合,因此无法用于重写查询。

    CREATE MATERIALIZED VIEW mv1 REFRESH ASYNC AS
    SELECT COUNT(DISTINCT cnt) 
    FROM (
        SELECT c_city, COUNT(*) cnt 
        FROM customer 
        GROUP BY c_city
    ) t;

    示例2:物化视图mv2使用了Join加聚合,因此无法用于重写查询。要解决这个问题,您可以创建一个带有聚合的物化视图,然后基于该物化视图创建带有Join的嵌套物化视图。

    CREATE MATERIALIZED VIEW mv2 REFRESH ASYNC AS
    SELECT *
    FROM (
        SELECT lect lo_orderkey, lo_custkey, p_partkey, p_name
        FROM lineorder
        JOIN part ON lo_partkey = p_partkey
    ) lo
    JOIN (
        SELECT c_custkey
        FROM customer
        GROUP BY c_custkey
    ) cust
    ON lo.lo_custkey = cust.c_custkey;

    示例3:物化视图mv3无法改写模式为SELECT c_city, sum(tax) FROM tbl WHERE dt='2023-01-01' AND c_city = 'xxx'的查询,因为谓词引用的列不在SELECT表达式中。

    CREATE MATERIALIZED VIEW mv3 REFRESH ASYNC AS
    SELECT c_city, SUM(tax) FROM tbl GROUP BY c_city;

    要解决这个问题,您可以按照以下方式创建物化视图。

    CREATE MATERIALIZED VIEW mv3 REFRESH ASYNC AS
    SELECT dt, c_city, SUM(tax) FROM tbl GROUP BY dt, c_city;