Exists 与 In 的物化视图性能

Gre*_*reg 5 sql oracle performance materialized-views

我做了一些谷歌搜索,但没有找到一个 oracle 性能问题的明确答案。也许我们可以在这里记录它。我正在构建一个非常简单但在相当大的桌子上的 MV。像许多事情一样的查询可以用不止一种方式编写。在我的情况下,当作为 select 语句编写时,两个解决方案具有相似的成本/执行计划,但是当放置在创建物化视图中时,执行时间会发生巨大变化。任何洞察为什么?

  • Tab1 大约有 40M 条记录。
  • Tab2 是大约 8M 记录。
  • field1 是 Tab1 上的主键,它不是 Tab2 上的 PK 或唯一键,但 Tab 2 确实在该字段上有索引。
  • field2 不是键,也不是在任一表上建立索引 (boo)

查询是:

问题 1:

SELECT
    CR1.Several_Fields
FROM 
    SCHEMA1.tab1 T1
WHERE T1.field2 like 'EXAMPLE%'
AND T1.field1 not in (
    SELECT T2.field1
    FROM SCHEMA1.tab2 T2
)
; 
Run Code Online (Sandbox Code Playgroud)

问题 2:

SELECT
    CR1.Several_Fields
FROM 
    SCHEMA1.tab1 T1
WHERE T1.field2 like 'EXAMPLE%'
AND  not exists (
    SELECT 1
    FROM SCHEMA1.tab2 T2
    WHERE T1.field1 = T2.field1
)
;
Run Code Online (Sandbox Code Playgroud)

两个查询作为 select 语句的运行时间相似,并且解释计划让它们都使用索引扫描而不是我所期望的全表扫描。出乎意料的是,当在 mv 创建中运行时,Q2 运行得更快(47 秒 vs 81 天每个 v$session_longops):

CREATE MATERIALIZED VIEW SCHEMA1.mv_blah as
(
  Q1 or Q2
);
Run Code Online (Sandbox Code Playgroud)

有没有人有任何见解,这里是否有一条规则,如果可能的话,只对 mviews 不使用 IN?当表之间不存在索引时,我知道 in 和 existing 之间的技巧,但这让我感到困惑。这是针对 oracle 11g 数据库运行的。

Ale*_*ole 3

这看起来像是一个已知的错误。如果您有权访问 My Oracle Support,请查看基于 NOT IN 定义查询的物化视图的缓慢创建/刷新(文档 ID 1591851.1),或者如果您没有访问权限,则不太有用,可以使用问题摘要

当然,这里无法复制 MOS 版本的内容,但足以说明唯一的解决方法是您已经在使用not exists. 它在 12c 中已修复,这对您没有多大帮助。