【问题标题】:Performance Degradation During Materialized View Complete Refresh With Indexes Active物化视图完全刷新期间索引处于活动状态时性能下降
【发布时间】:2020-08-04 00:11:37
【问题描述】:

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

Oracle 版本 12c

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

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

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

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

从 SQL Developer 报告的实时执行:~153s

获得性能:

SELECT elapsed_time, log_purge_time
FROM dba_mvref_stats
....

已用时间 = 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

有点惊讶,所以我一个一个地尝试,一次只有 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 只是为了测试。

【问题讨论】:

    标签: oracle indexing performance-testing materialized-views


    【解决方案1】:

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

    ALTER SESSION ENABLE PARALLEL DML;
    

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

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

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

    【讨论】:

    • 当我与其他人交谈时,我应该早点更新此内容,但您的解决方案是其他资深 Oracle 开发人员告诉我的。另外,我一直在寻找为什么会这样的原因,但是一旦向我解释了它就完全有道理了。如果我错了,您可以纠正我,因为我可能无法正确记住所有内容,但是因为完成刷新后,插入数据然后从头开始构建索引比从现有索引重新构建更容易。跨度>
    • 是的,没错。 atomic_refresh=>true,默认值,类似于 INSERT,DELETE。其他会话看到旧数据并完成新数据。 atomic_refresh=>FALSE 更像是 TRUNCATE+CREATE TABLE AS SELECT。第一个在交易上是安全的,但需要付出代价。第二个非常具有破坏性(如果刷新失败,则在有人修复之前没有数据),但速度更快。
    猜你喜欢
    • 2016-05-18
    • 2014-04-29
    • 1970-01-01
    • 2023-03-15
    • 2010-09-27
    • 2019-07-04
    • 2016-06-23
    • 1970-01-01
    • 2018-04-11
    相关资源
    最近更新 更多