刷新 MV 时,Oracle Materizalized 上的索引似乎不起作用

问题描述 投票:0回答:1

我创建了一个 Oracle 物化视图,它正在多个查询中进一步用作数据源。

由于MV有大量数据(大约200万),我在MV的其中一列上创建了索引。这提高了使用该 MV 作为源的查询的性能。

但是当 MV 完全刷新时,我观察到使用 MV 的查询再次开始显示性能问题。

是否是因为在完全刷新期间,索引被删除并重新创建?

我该如何解决这个问题? MV刷新持续了近1个半小时。这意味着在这 1.5 小时内,查询将无法及时提供数据。我需要保持每 3 小时或更短时间刷新一次 MV。

问候,

oracle indexing query-optimization materialized-views
1个回答
0
投票

这不是由于索引,而是由于所谓的“读取一致性”。您正在使用正常的原子刷新,它会删除所有行,然后在单个事务中将新行重新插入到它们的位置。这允许用户始终继续查看旧版本的表,直到刷新完成。但所有这些更改 - 插入和删除,都必须回滚以创建每个块的 CR(一致读取)版本,以便您的用户会话在刷新开始之前看到“使用”的内容。这需要从回滚段中进行大量读取,并且确实会严重降低查询性能。 您的另一个简单选择是使刷新成为非原子的,这将使刷新速度更快(执行截断而不是删除,并使用直接路径而不是传统插入重新加载),但表将非常有效地“空”为表创建一个下降期。这可能也无法接受。

如果以上都不可接受,有两种常见的解决方案:

创建两个 MV 和一个同义词。将同义词重新指向一个表,同时刷新另一个表,完成后指向新刷新的表。用户仅参考同义词,因此会被定向到最近完成的 MV。缺点是每次同义词翻转时都会导致光标和代码失效。但它有效。

  1. 根本不要使用 MV - 编写一个简单的过程,将查询结果加载到 GTT(全局临时表,位于临时空间中),然后对“MV”表(不是真正的 MV)执行两个 MERGE 语句,只是一个普通的表)。第一次合并插入新行并更新更改的行。第二次合并删除丢失的行。这远远优于任何真正的 MV 选项,因为它只更改需要更改的内容,而无需无缘无故地一遍又一遍地重新创建所有相同的数据。在发生这种情况时,其他读取会话将使用一致读取来查看数据的旧版本,但由于表的绝大多数内容尚未被触及,因此执行 CR 读取的回滚工作将是最小的,并且不会明显影响性能。对于始终需要高性能查询的重要“MV”,这已成为我的首选。

© www.soinside.com 2019 - 2024. All rights reserved.