异步物化视图问题排查
本主题介绍如何检查异步物化视图,以及如何解决使用过程中遇到的问题。
注意
以下显示的部分功能仅从 StarRocks v3.1 起支持。
检查异步物化视图
要全面了解您正在使用的异步物化视图,您可以首先检查它们的工作状态、刷新历史记录和资源消耗。
检查异步物化视图的工作状态
您可以使用 SHOW MATERIALIZED VIEWS 检查异步物化视图的工作状态。在返回的所有信息中,您可以关注以下字段
is_active
:物化视图的状态是否处于活动状态。只有活动的物化视图才能用于查询加速和重写。last_refresh_state
:上次刷新的状态,包括 PENDING、RUNNING、FAILED 和 SUCCESS。last_refresh_error_message
:上次刷新失败的原因(如果物化视图状态未激活)。rows
:物化视图中的数据行数。请注意,此值可能与物化视图的实际行数不同,因为更新可能会延迟。
有关返回的其他字段的详细信息,请参阅 SHOW MATERIALIZED VIEWS - 返回值。
示例
MySQL > SHOW MATERIALIZED VIEWS LIKE 'mv_pred_2'\G
***************************[ 1. row ]***************************
id | 112517
database_name | ssb_1g
name | mv_pred_2
refresh_type | ASYNC
is_active | true
inactive_reason | <null>
partition_type | UNPARTITIONED
task_id | 457930
task_name | mv-112517
last_refresh_start_time | 2023-08-04 16:46:50
last_refresh_finished_time | 2023-08-04 16:46:54
last_refresh_duration | 3.996
last_refresh_state | SUCCESS
last_refresh_force_refresh | false
last_refresh_start_partition |
last_refresh_end_partition |
last_refresh_base_refresh_partitions | {}
last_refresh_mv_refresh_partitions |
last_refresh_error_code | 0
last_refresh_error_message |
rows | 0
text | CREATE MATERIALIZED VIEW `mv_pred_2` (`lo_quantity`, `lo_revenue`, `sum`)
DISTRIBUTED BY HASH(`lo_quantity`, `lo_revenue`) BUCKETS 2
REFRESH ASYNC
PROPERTIES (
"replication_num" = "3",
"storage_medium" = "HDD"
)
AS SELECT `lineorder`.`lo_quantity`, `lineorder`.`lo_revenue`, sum(`lineorder`.`lo_tax`) AS `sum`
FROM `ssb_1g`.`lineorder`
WHERE `lineorder`.`lo_linenumber` = 1
GROUP BY 1, 2;
1 row in set
Time: 0.003s
查看异步物化视图的刷新历史记录
您可以通过查询数据库 information_schema
中的表 task_runs
来查看异步物化视图的刷新历史记录。在返回的所有信息中,您可以关注以下字段
CREATE_TIME
和FINISH_TIME
:刷新任务的开始时间和结束时间。STATE
:刷新任务的状态,包括 PENDING、RUNNING、FAILED 和 SUCCESS。ERROR_MESSAGE
:刷新任务失败的原因。
示例
MySQL > SELECT * FROM information_schema.task_runs WHERE task_name ='mv-112517' \G
***************************[ 1. row ]***************************
QUERY_ID | 7434cee5-32a3-11ee-b73a-8e20563011de
TASK_NAME | mv-112517
CREATE_TIME | 2023-08-04 16:46:50
FINISH_TIME | 2023-08-04 16:46:54
STATE | SUCCESS
DATABASE | ssb_1g
EXPIRE_TIME | 2023-08-05 16:46:50
ERROR_CODE | 0
ERROR_MESSAGE | <null>
PROGRESS | 100%
EXTRA_MESSAGE | {"forceRefresh":false,"mvPartitionsToRefresh":[],"refBasePartitionsToRefreshMap":{},"basePartitionsToRefreshMap":{}}
PROPERTIES | {"FORCE":"false"}
***************************[ 2. row ]***************************
QUERY_ID | 72dd2f16-32a3-11ee-b73a-8e20563011de
TASK_NAME | mv-112517
CREATE_TIME | 2023-08-04 16:46:48
FINISH_TIME | 2023-08-04 16:46:53
STATE | SUCCESS
DATABASE | ssb_1g
EXPIRE_TIME | 2023-08-05 16:46:48
ERROR_CODE | 0
ERROR_MESSAGE | <null>
PROGRESS | 100%
EXTRA_MESSAGE | {"forceRefresh":true,"mvPartitionsToRefresh":["mv_pred_2"],"refBasePartitionsToRefreshMap":{},"basePartitionsToRefreshMap":{"lineorder":["lineorder"]}}
PROPERTIES | {"FORCE":"true"}
监控异步物化视图的资源消耗
您可以监控和分析异步物化视图在刷新期间和刷新后的资源消耗。
监控刷新期间的资源消耗
在刷新任务期间,您可以使用 SHOW PROC '/current_queries' 监控其实时资源消耗。
在返回的所有信息中,您可以关注以下字段
ScanBytes
:扫描的数据大小。ScanRows
:扫描的数据行数。MemoryUsage
:使用的内存大小。CPUTime
:CPU 时间成本。ExecTime
:查询的执行时间。
示例
MySQL > SHOW PROC '/current_queries'\G
***************************[ 1. row ]***************************
StartTime | 2023-08-04 17:01:30
QueryId | 806eed7d-32a5-11ee-b73a-8e20563011de
ConnectionId | 0
Database | ssb_1g
User | root
ScanBytes | 70.981 MB
ScanRows | 6001215 rows
MemoryUsage | 73.748 MB
DiskSpillSize | 0.000
CPUTime | 2.515 s
ExecTime | 2.583 s
分析刷新后的资源消耗
在刷新任务之后,您可以通过查询 Profile 来分析其资源消耗。
在异步物化视图自行刷新时,将执行 INSERT OVERWRITE 语句。您可以检查相应的查询 Profile 来分析刷新任务消耗的时间和资源。
在返回的所有信息中,您可以关注以下指标
Total
:查询消耗的总时间。QueryCpuCost
:查询的总 CPU 时间成本。CPU 时间成本是为并发进程聚合的。因此,此指标的值可能大于查询的实际执行时间。QueryMemCost
:查询的总内存成本。- 单个运算符的其他指标,例如 Join 运算符和 Aggregate 运算符。
有关如何检查查询 Profile 和了解其他指标的详细信息,请参阅 分析查询 Profile。
验证查询是否被异步物化视图重写
您可以使用 EXPLAIN 从查询计划中检查查询是否可以使用异步物化视图重写。
如果查询计划中的指标 SCAN
显示相应物化视图的名称,则查询已被物化视图重写。
示例 1
MySQL > SHOW CREATE TABLE mv_agg\G
***************************[ 1. row ]***************************
Materialized View | mv_agg
Create Materialized View | 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 `ssb_1g`.`customer`
GROUP BY `customer`.`c_custkey`;
MySQL > EXPLAIN LOGICAL SELECT `customer`.`c_custkey`
-> FROM `ssb_1g`.`customer`
-> GROUP BY `customer`.`c_custkey`;
+-----------------------------------------------------------------------------------+
| Explain String |
+-----------------------------------------------------------------------------------+
| - Output => [1:c_custkey] |
| - SCAN [mv_agg] => [1:c_custkey] |
| Estimates: {row: 30000, cpu: ?, memory: ?, network: ?, cost: 15000.0} |
| partitionRatio: 1/1, tabletRatio: 12/12 |
| 1:c_custkey := 10:c_custkey |
+-----------------------------------------------------------------------------------+
如果您禁用查询重写功能,StarRocks 将采用常规查询计划。
示例 2
MySQL > SET enable_materialized_view_rewrite = false;
MySQL > EXPLAIN LOGICAL SELECT `customer`.`c_custkey`
-> FROM `ssb_1g`.`customer`
-> GROUP BY `customer`.`c_custkey`;
+---------------------------------------------------------------------------------------+
| Explain String |
+---------------------------------------------------------------------------------------+
| - Output => [1:c_custkey] |
| - AGGREGATE(GLOBAL) [1:c_custkey] |
| Estimates: {row: 15000, cpu: ?, memory: ?, network: ?, cost: 120000.0} |
| - SCAN [mv_bitmap] => [1:c_custkey] |
| Estimates: {row: 60000, cpu: ?, memory: ?, network: ?, cost: 30000.0} |
| partitionRatio: 1/1, tabletRatio: 12/12 |
+---------------------------------------------------------------------------------------+
诊断和解决问题
在这里,我们列出您在使用异步物化视图时可能遇到的一些常见问题以及相应的解决方案。
物化视图构建失败
如果您未能创建异步物化视图,即无法执行 CREATE MATERIALIZED VIEW 语句,您可以查看以下几个方面
-
检查您是否错误地使用了同步物化视图的 SQL 语句。
StarRocks 提供两种不同的物化视图:同步物化视图和异步物化视图。
用于创建同步物化视图的基本 SQL 语句如下
CREATE MATERIALIZED VIEW <mv_name>
AS <query>但是,用于创建异步物化视图的 SQL 语句包含更多参数
CREATE MATERIALIZED VIEW <mv_name>
REFRESH ASYNC -- The refresh strategy of the asynchronous materialized view.
DISTRIBUTED BY HASH(<column>) -- The data distribution strategy of the asynchronous materialized view.
AS <query>除了 SQL 语句之外,两种物化视图之间的主要区别在于,异步物化视图支持 StarRocks 提供的所有查询语法,但同步物化视图仅支持有限的聚合函数选择。
-
检查您是否指定了正确的分区列。
创建异步物化视图时,您可以指定分区策略,这使您可以更精细地刷新物化视图。
当前,StarRocks 仅支持范围分区,并且仅支持引用用于构建物化视图的查询语句中 SELECT 表达式中的单个列。您可以使用 date_trunc() 函数截断列以更改分区策略的粒度级别。请注意,不支持任何其他表达式。
-
检查您是否具有创建物化视图所需的权限。
创建异步物化视图时,您需要查询的所有对象(表、视图、物化视图)的 SELECT 权限。如果在查询中使用 UDF,则还需要函数的 USAGE 权限。
物化视图刷新失败
如果物化视图刷新失败,即刷新任务的状态不是 SUCCESS,您可以查看以下几个方面
-
检查您是否采用了不适当的刷新策略。
默认情况下,物化视图在创建后立即刷新。但是,在 v2.5 及早期版本中,采用 MANUAL 刷新策略的物化视图在创建后不会刷新。您必须使用 REFRESH MATERIALIZED VIEW 手动刷新它。
-
检查刷新任务是否超出内存限制。
通常,当异步物化视图涉及大规模聚合或 Join 计算时,会耗尽内存资源。要解决此问题,您可以
- 为物化视图指定分区策略,以便每次刷新一个分区。
- 为刷新任务启用溢写到磁盘功能。从 v3.1 开始,StarRocks 支持在刷新物化视图时将中间结果溢写到磁盘。执行以下语句以启用溢写到磁盘
-- Define the properties when creating the materialized view.
CREATE MATERIALIZED VIEW mv1
REFRESH ASYNC
PROPERTIES ( 'session.enable_spill'='true' )
AS <query>;
-- Add the properties to an existing materialized view.
ALTER MATERIALIZED VIEW mv2 SET ('session.enable_spill' = 'true');
物化视图刷新超时
大型物化视图可能无法刷新,因为刷新任务超过了超时时间。您可以考虑以下解决方案来解决此问题
-
为物化视图指定分区策略以实现细粒度刷新
如 创建分区物化视图 中所述,通过对物化视图进行分区,您可以实现增量构建和刷新,从而避免了初始刷新期间过度消耗资源的问题。
-
设置更长的超时时间
物化视图刷新任务的默认超时时间在 v3.2 之前的版本中为 5 分钟,在 v3.2 及更高版本中为 1 小时。如果您遇到超时异常,可以使用以下语句调整超时时间
ALTER MATERIALIZED VIEW mv2 SET ('session.insert_timeout' = '4000');
-
分析物化视图刷新的性能瓶颈
刷新具有复杂计算的物化视图非常耗时。您可以通过分析刷新任务的查询 Profile 来分析其性能瓶颈
- 通过查询
information_schema.task_runs
获取与刷新任务对应的query_id
。 - 使用以下语句分析刷新任务的查询 Profile
- GET_QUERY_PROFILE:根据
query_id
检索原始查询 Profile。 - ANALYZE PROFILE:按 Fragment 分析查询 Profile,并以树状结构显示。
- GET_QUERY_PROFILE:根据
- 通过查询
物化视图状态未激活
如果物化视图无法重写查询或刷新,并且物化视图的 is_active
状态为 false
,则可能是由于基表的 Schema 更改导致的。要解决此问题,您可以执行以下语句手动将物化视图状态设置为活动
ALTER MATERIALIZED VIEW mv1 ACTIVE;
如果将物化视图状态设置为活动状态不起作用,则需要删除物化视图并重新创建它。
物化视图刷新任务使用过多的资源
如果您发现刷新任务正在使用过多的系统资源,您可以查看以下几个方面
-
检查您是否创建了过大的物化视图。
如果您 Join 了太多的表导致大量的计算,则刷新任务将占用许多资源。要解决此问题,您需要评估物化视图的大小并重新规划它。
-
检查您是否设置了不必要的频繁刷新间隔。
如果您采用固定间隔刷新策略,则可以设置较低的刷新频率来解决此问题。如果刷新任务是由基表中的数据更改触发的,则过于频繁地加载数据也会导致此问题。要解决此问题,您需要为物化视图定义适当的刷新策略。
-
检查物化视图是否已分区。
未分区的物化视图刷新成本可能很高,因为 StarRocks 每次都会刷新整个物化视图。要解决此问题,您需要为物化视图指定分区策略,以便每次刷新一个分区。
要停止占用过多资源的刷新任务,您可以
-
将物化视图状态设置为非活动状态,以便停止其所有刷新任务
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 及更高版本中可用,此命令提供重写失败的简洁原因。
MySQL > TRACE REASON MV SELECT sum(c1) FROM `glue_ice`.`iceberg_test`.`ice_test3`;
+----------------------------------------------------------------------------------------------------------------------+
| Explain String |
+----------------------------------------------------------------------------------------------------------------------+
| MV rewrite fail for mv1: Rewrite aggregate rollup sum(1: c1) failed: only column-ref is supported after rewrite |
| MV rewrite fail for mv1: Rewrite aggregate function failed, cannot get rollup function: sum(1: c1) |
| MV rewrite fail for mv1: Rewrite rollup aggregate failed: cannot rewrite aggregate functions |
+----------------------------------------------------------------------------------------------------------------------+ -
检查物化视图和查询是否匹配。
- StarRocks 使用基于结构的匹配技术而不是基于文本的匹配来匹配物化视图和查询。因此,不能保证查询可以被重写,仅仅因为它看起来类似于物化视图的查询。
- 物化视图只能重写 SPJG(Select/Projection/Join/Aggregation)类型的查询。不支持涉及窗口函数、嵌套聚合或 Join 加聚合的查询。
- 物化视图无法重写在 Outer Joins 中涉及复杂 Join 谓词的查询。例如,在类似
A LEFT JOIN B ON A.dt > '2023-01-01' AND A.id = B.id
的情况下,我们建议您在WHERE
子句中指定来自JOIN ON
子句的谓词。
有关物化视图查询重写的更多信息,请参阅 使用物化视图的查询重写 - 限制。
-
检查物化视图状态是否为活动状态。
StarRocks 在重写查询之前会检查物化视图的状态。只有当物化视图状态为活动状态时,才能重写查询。要解决此问题,您可以执行以下语句手动将物化视图状态设置为活动
ALTER MATERIALIZED VIEW mv1 ACTIVE;
-
检查物化视图是否满足数据一致性要求。
StarRocks 检查物化视图和基表数据中的数据一致性。默认情况下,只有当物化视图中的数据是最新的时,才能重写查询。要解决此问题,您可以
- 将
PROPERTIES('query_rewrite_consistency'='LOOSE')
添加到物化视图以禁用一致性检查。 - 添加
PROPERTIES('mv_rewrite_staleness_second'='5')
以容忍一定程度的数据不一致。如果上次刷新在此时间间隔之前,则可以重写查询,无论基表中的数据是否更改。
- 将
-
检查物化视图的查询语句是否缺少输出列。
要重写范围和点查询,您必须在物化视图的查询语句的 SELECT 表达式中指定用作过滤谓词的列。您需要检查物化视图的 SELECT 语句,以确保它包含查询的 WHERE 和 ORDER 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 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;