在索引处于活动状态的情况下,物化视图完全刷新期间性能下降

Performance Degradation During Materialized View Complete Refresh With Indexes Active

问题:当索引处于活动状态时,完全刷新期间性能显着下降。我不太确定为什么在完全刷新期间激活索引会导致性能显着差异。目前我们的数据仓库存在过度索引的问题,但我惊讶地发现即使只有一个活动索引与完全刷新时没有活动索引相比性能也会大幅下降。

Oracle 版本 12c

研究: Materialized view refresh terrible performance degradation 我在 SO 上找到了这个,但它不一定能回答我为什么索引会导致性能下降的问题。我可能会继续执行删除索引并在完全刷新后重建的建议,但我仍在尝试找出原因。

示例性能测试: 我有很多 MV,但这是我如何测试 MV 和相关成本的示例。我测试了大约 10 个 MV,它们都显示相同的模式。请注意,我修改了代码以删除所有对象名称

所有索引都处于活动状态:

exec dbms_mview.refresh('MY_MV_TEST','C');

来自 SQL 开发者的实时执行报告:~153s

取得成绩:

SELECT elapsed_time, log_purge_time
FROM dba_mvref_stats
....

elapsed_time = 151 log_purge_time = 1

ALTER INDEX IX_MY_MV_TEST_1 UNUSABLE;
....
ALTER INDEX IX_MY_MV_TEST_13 UNUSABLE;

重新运行完成刷新:

exec dbms_mview.refresh('MY_MV_TEST','C');

从dba_mvref_stats获取统计数据:

elapsed_time = 27 log_purge_time = 1

有点惊讶,所以我一个一个地尝试,一次只有一个索引处于活动状态。对于每个索引,报告的 elapsed_time 为 33,log_purge_time 为 2(我认为这有点奇怪,它们也都同时报告)。还有一些其他的 MV 也从 300 年代到 40 年代。到目前为止,我只在我们数据仓库的一小部分上进行了测试,我假设我们的一些较大的 MV 会显示相同的结果。据 SQL 开发人员报告,重建索引仅需 11 秒。

MV DDL: 重命名所有对象需要一些时间,但如果需要的话我会的。现在,这是这个特定 MV 定义的总体概览。在 SELECT 子句中只有列、一对 case 语句、一对 substr() 和 cast()。

CREATE MATERIALIZED VIEW MY_MV_TEST 
BUILD DEFERRED 
USING INDEX REFRESH FORCE ON DEMAND 
USING DEFAULT LOCAL ROLLBACK SEGMENT
USING ENFORCED CONSTRAINTS AS
SELECT column1, column2, CASE..., SUBSTR(..), CAST()...
FROM mv1, mv2, mv3
WHERE mv1.column1 = mv2.column1
AND mv1.column1 = mv3.column1
AND ... (other simple conditions using the equality operator)

另请注意,我测试过的所有 MV 都具有 REFRESH FAST 功能。 DBMS_MVIEW.EXPLAIN_MVIEW 表明它们具有 REFRESH FAST 能力。我使用 COMPLETE REFRESH 只是为了测试。

请检查它是否有助于运行并行刷新:

ALTER SESSION ENABLE PARALLEL DML;

此外,将刷新切换为非原子刷新:

EXEC dbms_mview.refresh(list=>'MY_MV_TEST', method=>'C', atomic_refresh=>false);

然后 Oracle 将自动禁用索引、刷新数据并重建索引,这在大多数情况下会更快。